I was wrong, there's another alternative using just the Django admin app.
In the admin.py for your app, you can define a renderer for the contents of a table cell. Here's the variant for my film library:
class FilmAdmin(admin.ModelAdmin):
def film_status(self, obj):
if obj.status() != 'active':
return '<div style="width:100%%; height:100%%; background-color:orange;">%s</div>' % obj.status()
return obj.status()
film_status.allow_tags = True
list_display = ('id', 'title', 'film_status')
admin.site.register(Film, FilmAdmin)
Here, I've created a field name, 'film_status', that does not exist in the Film model, and defined it as a method of FilmAdmin. It gets passed the item for every row. I've had to tell the renderer to allow_tags, which tells the admin app not to "safe" the HTML content.
This won't fill the whole cell, though, as the cell itself has some padding. Only the part of the cell your app is allowed to fill (as defined by the admin's stylesheet) will be filled. But it's good enough for my purposes.
There you go. Two completely different, but useful, techniques for decorating the content of a cell in a Django admin list.