(One of my summaries of a talk at the 2015 django under the hood conference).
Ola Sitarska gave a higher-level talk about the django admin at the recent Cardiff djangocon. She loves the django admin.
The django admin hasn’t seen any big updates for the last 8 years. It just works and it works well and it is stable. Until django 1.9: there’s a new visual skin for the admin. Check it out! (She showed a screenshot later on in the presentation: yes, it looks great!)
There are three main parts to the django admin: AdminSite, ModelAdmin, ChangeList.
The AdminSite encapsulates an instance of the django admin application.
You don’t need to do
admin.autodiscover() anymore as it is called
automatically by Django now that django has a signal for when an app is
loaded. For the admin app, it fires off
Autodiscover finds all your models and extracts information about
them. Including the
admin.py customization/configuration. This ends up as
a list of admin URLs.
Note: you can have multiple admins with different configurations in case you have a need for two completely differently configured admin sites.
Some of the things you can customize on an adminsite are the
If you want to change something globally in your admin, the AdminSite is probably the place to do it.
The ModelAdmin contains all the admin options and functionality for any given model.
The AdminSite autodiscover looks at the
admin.py files. There you can
configure the ModelAdmin for your models. There are a lot of options you
A modeladmin can have a custom
get_urls() method. In this way you can
customize or even add pages to your admin for the model. Normally you have
a add_view, change_view, etc. You can also pass in different form
You can hook into the permission machinery with methods like
has_change_permission(self, request, obj=None).
But… all those hooks and especially the form handling for the change form makes things hard. You might be better off writing your own view.
A good way to customize a model admin is to pass in a custom
A gotcha: a modeladmin is initialized when django starts up, not for every
request. So watch out with saving things on
raw_id_fields when there are a lot of items your foreignkey can
point at. Rendering the admin page can take a long time, then. Raw id fiels
only contain the primary key and a handy search box.
The Changelist is the overview page that lists the objects available of your model.
It is an internal component that makes sure your actions and filters are always up to date. It does a good job. But there is no documentation for it. There is no API. There are lots of things you can customize, though.
Some of the things it does: what are the filters? What is searched? Order? Pagination? Pagination params in the query string? Etc.
Filters are handy. Normally you just pass in the name of a field. But you
can also pass in a filter class.
DecadeBornListFilter. And you can write your own! An example:
class RelevantPortalFilter(admin.SimpleListFilter): title = _('portal') parameter_name = 'portal__id__exact' def lookups(self, request, model_admin): return models.Portal.objects.filter( roles__isnull=False).distinct().values_list( 'id', 'name') def queryset(self, request, queryset): if not self.value(): return queryset return queryset.filter(portal=self.value())
(Note by Reinout: I copied that code from some code I recently wrote myself instead of typing over from the presentation)
A customization point:
get_queryset(), this should return the objects
you want to show.
get_results() actually calls
get_paginator(). It looks at
get_filters_params() that grab the filters and their GET parameters and
checks them for validity.
Those filters are then applied to the queryset. Afterwards the ordering is
get_ordering() in the admin. Then default ordering in the
model. And it looks at ordering that might be applied by the user in the
Next step: searching with
get_search_results() if you’ve defined
search_fields on which to do a textual search.
So: the admin can be customized a lot and it is a nice part of Django.
Image: cycling on former railways this summer. This is the railway tunnel at Neuerburg, Germany.
My name is Reinout van Rees and I work a lot with Python (programming language) and Django (website framework). I live in The Netherlands and I'm happily married to Annie van Rees-Kooiman.
Most of my website content is in my weblog. You can keep up to date by subscribing to the automatic feeds (for instance with Google reader):