Django Introduction Part4 - Admin
Generating admin sites for your staff or clients to add, change, and delete content is tedious work that doesn’t require much creativity. For that reason, Django entirely automates creation of admin interfaces for models to build a site area that you can use to create, view, update, and delete records.
Creating a superuser
The admin isn’t intended to be used by site visitors. It’s for site managers.
In order to log into the admin site, we need a user account with Staff status enabled.
In order to view and create records we also need this user to have permissions to manage all our objects. You can create a “superuser” account that has full access to the site and all needed permissions using manage.py.
Call the following command, in the same directory as manage.py, to create the superuser. You will be prompted to enter a username, email address, and strong password.
1 | $ python manage.py createsuperuser |
If this
Superuser creation skipped due to not running in a TTY.happens in your terminal, you can try
winpty python manage.py createsuperuserto avoid the errors.
Enter your desired username and press enter.
1 | Username: mv |
You will then be prompted for your desired email address:
1 | Email address: |
The final step is to enter your password. You will be asked to enter your password twice, the second time as a confirmation of the first.
1 | Password: theater |
Once this command completes, a new superuser will have been added to the database.
The Django admin site is activated by default. Let’s start the development server and explore it.
1 | $ python manage.py runserver 8080 |
Now, open a Web browser and go to “/admin/” on your local domain – e.g., http://127.0.0.1:8080/admin/. You should see the admin’s login screen:
Since translation is turned on by default, the login screen may be displayed in your own language, depending on your browser’s settings and if Django has a translation for this language.
You should see a few types of editable content: groups and users. They are provided by django.contrib.auth, the authentication framework shipped by Django.
Django Admin
Just one thing to do: we need to tell the admin that Movie objects have an admin interface. To do this, open the ratings/admin.pyfile, and edit it to look like this:
1 | from django.contrib import admin |

This is the simplest way of registering a model, or models, with the site. The admin site is highly customizable, and we’ll talk more about the other ways of registering your models further down.
Advanced configuration
Django does a pretty good job of creating a basic admin site using the information from the registered models:
- Each model has a list of individual records, identified by the string created with the model’s
__str__()method, and linked to detail views/forms for editing. By default, this view has an action menu at the top that you can use to perform bulk delete operations on records. - The model detail record forms for editing and adding records contain all the fields in the model, laid out vertically in their declaration order.
You can further customize the interface to make it even easier to use.
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 Movie model. Open admin.py in the your application. Now add a new MovieAdmin and registration as shown below.
1 | # Define the admin class |
We can also instead use the @register decorator to register the models (this does exactly the same thing as the admin.site.register() syntax):
1 |
|
For our Movie model we’ll additionally display the movie_title and director. The director is a ForeignKey field (one-to-many) relationship, and so will be represented by the __str__()value for the associated record.
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).
Note: Getting the genre may not be a good idea here, because of the “cost” of the database operation.
Add the following code into your Movie 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.
1 | def display_genre(self): |
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.
1 | class Movieadmin(admin.ModelAdmin): |
The list view will now include a filter box to the right. Note how you can choose dates and status to filter the values:).
Let’s add some search capability:
1 | search_fields = ['movie_title'] |
That adds a search box at the top of the change list. When somebody enters search terms, Django will search the movie_title field. You can use as many fields as you’d like – although because it uses a LIKE query behind the scenes, limiting the number of search fields to a reasonable number will make it easier for your database to do the search
Organize 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 organize the information, whether fields are displayed horizontally or vertically, and even what edit widgets are used in the admin forms.
Update your AuthorAdmin class to add the fields line, as shown below (in bold):
1 | fields: [('movie_title', 'movie_title_CN','movie_title2'), 'movie_poster','movie_language','movie_country','movie_release_date','movie_time','movie_genres'] |
The fields attribute lists just those fields that are to be displayed on the form, in order. Fields are displayed vertically by default, but will display horizontally if you further group them in a tuple.
You can add “sections” to group related model information within the detail form, using the fieldsets attribute.
1 | fieldsets = ( |
Each section has its own title (or None, if you don’t want a title) and an associated tuple of fields in a dictionary — the format is complicated to describe, but fairly easy to understand if you look at the code fragment immediately above.
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 movie information and information about the specific rating 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). For example:
1 | ## StackedInline will take a lot of screen space to display all the fields |
Now navigate to a view for a Movie in your website — at the bottom you should now see the rating instances relating to this movie.
Django administration
Clearly, having “Django administration” at the top of each admin page is ridiculous. It’s just placeholder text.
That’s easy to change, though, using Django’s template system. The Django admin is powered by Django itself, and its interfaces use Django’s own template system.
Now create a directory called admin inside your project templates folder, and copy the template admin/base_site.html from within the default Django admin template directory in the source code of Django itself (django/contrib/admin/templates) into that directory.
If you have difficulty finding where the Django source files are located on your system, run the following command:
1 | $ python -c "import django; print(django.__path__)" |
1 | ['D:\\Anaconda3\\lib\\site-packages\\django'] |
Then, just edit the file and replace {{ site_header|default:_('Django administration') }} (including the curly braces) with your own site’s name as you see fit. You should end up with a section of code like:
1 | {% block branding %} |
We use this approach to teach you how to override templates. In an actual project, you would probably use the django.contrib.admin.AdminSite.site_headerattribute to more easily make this particular customization.






