The admin site
Django comes with a complete admin site: a password-protected interface where staff can add, change and delete data in any model, with almost no code. For many projects, it replaces a whole internal tool.
Logging in
The admin is switched on in every new project: django.contrib.admin is in INSTALLED_APPS, and config/urls.py contains path("admin/", admin.site.urls). Create an account that may use it:
python manage.py createsuperuserUsername: asha
Email address: asha@example.com
Password:
Password (again):
Superuser created successfully.Run python manage.py runserver and open http://127.0.0.1:8000/admin/. After logging in, you'll see the Users and Groups models from django.contrib.auth, but not yet your own.
Registering a model
In the app's admin.py:
from django.contrib import admin
from .models import Course
admin.site.register(Course)Refresh the admin, and Courses appears, with pages to list, add, edit and delete courses. The forms are built from the model's fields, with validation, drop-downs for choices and date pickers for dates. The list shows each object using its __str__ method, which is why every model should have one.
Customising the list page
from django.contrib import admin
from .models import Course
@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
list_display = ["title", "category", "price", "published"] # columns on the list page
list_filter = ["category", "published"] # a filter sidebar
search_fields = ["title", "description"] # a search box
list_editable = ["price", "published"] # edit right in the list
ordering = ["title"]
prepopulated_fields = {"slug": ("title",)} # fill the slug as you type the title| Option | Adds |
|---|---|
list_display | columns on the list page, which can include model methods |
list_filter | a sidebar for narrowing the list down by field |
search_fields | a search box over those fields |
list_editable | fields that can be edited directly in the list |
date_hierarchy | navigation by year, month and day for a date field |
readonly_fields | fields shown but not editable |
@admin.register(Course) does the same as admin.site.register(Course, CourseAdmin), written as a decorator.
Editing related objects together
class LessonInline(admin.TabularInline):
model = Lesson
extra = 1 # one empty row for adding a new lesson
@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
list_display = ["title", "lesson_count"]
inlines = [LessonInline]
@admin.display(description="Lessons")
def lesson_count(self, obj):
return obj.lessons.count()An inline shows a course's lessons as a table on the course's edit page, so both can be edited at once. A method like lesson_count can appear in list_display as a calculated column.
Bulk actions
@admin.action(description="Publish the selected courses")
def publish(modeladmin, request, queryset):
updated = queryset.update(published=True)
modeladmin.message_user(request, f"{updated} courses published.")
@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
actions = [publish]Tick some rows on the list page, pick Publish the selected courses from the Action menu, and the function runs on the selected objects.