(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()
.
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 site_title
and site_header
, login_form
, index_template
etc.
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
can tweak.
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
templates.
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 form
or
add_form
.
A gotcha: a modeladmin is initialized when django starts up, not for every
request. So watch out with saving things on self
.
Handy: 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. BooleanListFilter()
, for
instance. 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_queryset()
. It
might use get_paginator()
. It looks at get_filters()
and
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
applied: 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
user interface.
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 program in Python, I live in the Netherlands, I cycle recumbent bikes and I have a model railway.
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):