3. Django admin site - LiVanych/locallibrary GitHub Wiki
All the configuration required to include the admin application in your website was done automatically when you created the skeleton project (for information about actual dependencies needed, see the Django docs here). As a result, all you must do to add your models to the admin application is to register them. At the end of this article we'll provide a brief demonstration of how you might further configure the admin area to better display our model data.
After registering the models we'll show how to create a new "superuser", login to the site, and create some books, authors, book instances, and genres. These will be useful for testing the views and templates we'll start creating in the next tutorial.
Registering models
vim catalog/admin.py
from django.contrib import admin
# Register your models here.
from catalog.models import Author, Genre, Book, BookInstance, Language
admin.site.register(Book)
admin.site.register(Author)
admin.site.register(Genre)
admin.site.register(BookInstance)
admin.site.register(Language)
Creating a superuser
python3 manage.py createsuperuser
python3 manage.py runserver
Logging in and using the site
Add books, authors, genres, languages and bookInstances.
Advanced configuration
You can further customise the interface to make it even easier to use. Some of the things you can do are:
List views: Add additional fields/information displayed for each record. Add filters to select which records are listed, based on date or some other selection value (e.g. Book loan status). Add additional options to the actions menu in list views and choose where this menu is displayed on the form.
Detail views: Choose which fields to display (or exclude), along with their order, grouping, whether they are editable, the widget used, orientation etc. Add related fields to a record to allow inline editing (e.g. add the ability to add and edit book records while you're creating their author record).
You can find a complete reference of all the admin site customisation choices in The Django Admin site (Django Docs).
Register a ModelAdmin class
To change how a model is displayed in the admin interface you define a ModelAdmin class (which describes the layout) and register it with the model.
Let's start with the Author
model. Open admin.py
in the catalog application
(/locallibrary/catalog/admin.py
). Comment out your original registration (prefix it with a #)
for the Author
model:
# admin.site.register(Author)
Now add a new AuthorAdmin
and registration as shown below.
# Define the admin class
class AuthorAdmin(admin.ModelAdmin):
pass
# Register the admin class with the associated model
admin.site.register(Author, AuthorAdmin)
Now we'll add ModelAdmin
classes for Book
, and BookInstance
. We again need to comment out the
original registrations:
# admin.site.register(Book)
# admin.site.register(BookInstance)
Now to create and register the new models; for the purpose of this demonstration, we'll instead
use the @register
decorator to register the models (this does exactly the same thing as the
admin.site.register()
syntax):
# Register the Admin classes for Book using the decorator
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
pass
# Register the Admin classes for BookInstance using the decorator
@admin.register(BookInstance)
class BookInstanceAdmin(admin.ModelAdmin):
pass
Currently all of our admin classes are empty (see pass) so the admin behaviour will be unchanged! We can now extend these to define our model-specific admin behaviour.
Configure list views
Replace your AuthorAdmin
class with the code below. The field names to be displayed in the list
are declared in a tuple in the required order, as shown (these are the same names as specified
in your original model).
class AuthorAdmin(admin.ModelAdmin):
list_display = ('last_name', 'first_name', 'date_of_birth', 'date_of_death')
For our Book
model we'll additionally display the author and genre. The author is a ForeignKey
field (one-to-one) relationship, and so will be represented by the __str__()
value for the
associated record. Replace the BookAdmin
class with the version below.
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'display_genre')
Unfortunately we can't directly specify the genre field in list_display because it is a
ManyToManyField
(Django prevents this because there would be a large database access "cost"
in doing so). Instead we'll define a display_genre
function to get the information as a string
(this is the function we've called above; we'll define it below).
Add the following code into your Book
model (models.py
). This creates a string from the first
three values of the genre field (if they exist) and creates a short_description
that can be
used in the admin site for this method.
def display_genre(self):
"""Create a string for the Genre.
This is required to display genre in Admin.
"""
return ', '.join(genre.name for genre in self.genre.all()[:3])
display_genre.short_description = 'Genre'
Add list filters
Once you've got a lot of items in a list, it can be useful to be able to filter which items
are displayed. This is done by listing fields in the list_filter
attribute. Replace your
current BookInstanceAdmin
class with the code fragment below.
class BookInstanceAdmin(admin.ModelAdmin):
list_display = ('book','id', 'imprint', 'status', 'due_back')
list_filter = ('status', 'due_back')
Organise detail view layout
By default, the detail views lay out all fields vertically, in their order of declaration in the model. You can change the order of declaration, which fields are displayed (or excluded), whether sections are used to organise the information, whether fields are displayed horizontally or vertically, and even what edit widgets are used in the admin forms.
Controlling which fields are displayed and laid out
Update your AuthorAdmin
class to add the fields line, as shown below:
class AuthorAdmin(admin.ModelAdmin):
list_display = (
'last_name', 'first_name',
'date_of_birth', 'date_of_death'
)
fields = ['first_name', 'last_name', ('date_of_birth', 'date_of_death')]
Note: You can also use the exclude attribute to declare a list of attributes to be excluded from the form (all other attributes in the model will be displayed).
class AuthorAdmin(admin.ModelAdmin):
list_display = ('last_name', 'first_name', 'date_of_birth', 'date_of_death')
exclude = ('date_of_death',)
Sectioning the detail view
You can add "sections" to group related model information within the detail form, using the fieldsets attribute.
In the BookInstance
model we have information related to what the book is (i.e. name
, imprint
,
and id
) and when it will be available (status
, due_back
). We can add these in different sections
by adding the text to our BookInstanceAdmin
class.
@admin.register(BookInstance)
class BookInstanceAdmin(admin.ModelAdmin):
list_display = ('book','id', 'imprint', 'status', 'due_back')
list_filter = ('status', 'due_back')
fieldsets = (
(None, {
'fields': ('book', 'imprint', 'id')
}),
('Availability', {
'fields': ('status', 'due_back')
}),
)
Inline editing of associated records
Sometimes it can make sense to be able to add associated records at the same time. For example, it may make sense to have both the book information and information about the specific copies you've got on the same detail page.
You can do this by declaring inlines
, of type TabularInline
(horizonal layout) or StackedInline
(vertical layout, just like the default model layout). You can add the BookInstance
information
inline to our Book
detail by adding the lines below near your BookAdmin
:
class BooksInstanceInline(admin.TabularInline):
model = BookInstance
extra = 0
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'display_genre')
inlines = [BooksInstanceInline]
The same for Book and Author models:
class BookInline(admin.TabularInline):
model = Book
extra = 0
# Define the admin class
class AuthorAdmin(admin.ModelAdmin):
list_display = ('last_name', 'first_name', 'date_of_birth', 'date_of_death')
inlines = [BookInline]
Further reading
Writing your first Django app, part 2: Introducing the Django Admin (Django docs)
The Django Admin site (Django Docs)