The Django Admin
Reviewed & published by Brayan K
The Django admin is an automatically generated, production-ready web interface that lets you create, read, update, and delete your model data through a browser, with no extra code beyond registering your models.
Part of the free Django course at LearnCodingFast — hands-on lessons with worked examples and the output they print, plus practice exercises and a quick quiz.
In this lesson you'll enable the admin, create a superuser to log in, register your first model so it appears in the interface, and then customise the list view to make managing data fast and pleasant.
What You'll Learn in This Lesson
- What the Django admin is and who it's for
- How to create a superuser with createsuperuser
- Logging in at the /admin/ URL
- Registering a model with admin.site.register
- Customising the list view with a ModelAdmin
- Using list_display, list_filter, and search_fields
1 Enabling the Admin and Creating a Superuser
The admin is enabled by default in a fresh project — django.contrib.admin is already listed in INSTALLED_APPS, and the /admin/ route is wired up in your project's urls.py. Before you can log in, you need to run migrations and create an administrator account.
# 1. Create the database tables the admin and auth system need
python manage.py migrate
# 2. Create an administrator account
python manage.py createsuperuser
# Username: admin
# Email address: admin@example.com
# Password: ********
# Superuser created successfully.
# 3. Start the server and open the admin
python manage.py runserver
# Visit http://127.0.0.1:8000/admin/ and log in# createsuperuser collects three things, then validates the password.
# Here's a simplified, plain-Python simulation of that flow so you can
# see what the command is doing under the hood.
def create_superuser(username, email, password):
if len(password) < 8:
return "Error: password too short (must be 8+ characters)."
account = {
"username": username,
"email": email,
"is_staff": True,
"is_superuser": True,
}
return f"Superuser created successfully: {account}"
# Simulate the prompts you'd answer in the terminal
print(create_superuser("admin", "admin@example.com", "supersecret"))
print(create_superuser("weak", "weak@example.com", "123"))
# EXPECTED:
# the first line succeeds, the second reports a too-short password.
# ✅ Expected output:
# Superuser created successfully: {'username': 'admin', 'email': 'admin@example.com', 'is_staff': True, 'is_superuser': True}
# Error: password too short (must be 8+ characters).2 Registering a Model
After logging in you'll only see the built-in Users and Groups sections. To manage your own data, you register a model in your app's admin.py file. A single call to admin.site.register gives you full add, edit, list, and delete pages.
Suppose you have a Post model in blog/models.py:
# blog/models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
slug = models.SlugField(unique=True)
body = models.TextField()
published = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.titleRegister it in blog/admin.py:
# blog/admin.py
from django.contrib import admin
from .models import Post
admin.site.register(Post)Refresh /admin/ and a Posts section appears. The __str__ method matters here: it controls the label Django shows for each row, so Post object (1) becomes the actual post title.
# Registering a model just adds it to a registry that the admin reads.
# This mini "admin site" mirrors that idea in plain Python.
class AdminSite:
def __init__(self):
self.registry = {}
def register(self, model_name):
self.registry[model_name] = "auto-generated CRUD pages"
def sections(self):
return sorted(self.registry.keys())
admin_site = AdminSite()
# Out of the box the admin knows about Users and Groups
admin_site.register("User")
admin_site.register("Group")
# Now register our own model, just like admin.site.register(Post)
admin_site.register("Post")
print("Admin sections:", admin_site.sections())
print("Post pages:", admin_site.registry["Post"])
# EXPECTED:
# Admin sections: ['Group', 'Post', 'User']
# Post pages: auto-generated CRUD pages
# ✅ Expected output:
# Admin sections: ['Group', 'Post', 'User']
# Post pages: auto-generated CRUD pages3 Customising with a ModelAdmin Class
A bare registration works, but the list page only shows the __str__ value. To control which columns appear, add filters, a search box, and an auto-filled slug, you define a ModelAdmin subclass and attach it with the @admin.register decorator.
# blog/admin.py
from django.contrib import admin
from .models import Post
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
list_display = ("title", "author", "published", "created_at")
list_filter = ("published", "created_at")
search_fields = ("title", "body")
prepopulated_fields = {"slug": ("title",)}- list_display — the columns shown in the list view, e.g. ("title", "author").
- list_filter — adds a filter sidebar for the named fields.
- search_fields — adds a search box that queries those fields.
- prepopulated_fields — auto-fills one field from another, e.g. a slug from the title.
# list_display picks which fields become columns in the list view.
# We'll simulate it by printing only the chosen fields of each "row".
list_display = ("title", "published")
posts = [
{"title": "Hello World", "author": "Alice", "published": True},
{"title": "Django Tips", "author": "Bob", "published": False},
{"title": "Admin Power", "author": "Carol", "published": True},
]
# Print a header row, then one row per post using only list_display fields
print(" | ".join(list_display))
print("-" * 24)
for post in posts:
row = [str(post[field]) for field in list_display]
print(" | ".join(row))
# EXPECTED: a two-column table of title and published for each post.
# ✅ Expected output:
# title | published
# ------------------------
# Hello World | True
# Django Tips | False
# Admin Power | True🎯 Your Turn: Register the Right Model
Fill in the blank so the function builds the correct registration line for a model named Post.
# 🎯 YOUR TURN: replace ___ with the model name "Post"
def registration_line(model_name):
return f"admin.site.register({model_name})"
model = "___"
print(registration_line(model))
# EXPECTED OUTPUT:
# admin.site.register(Post)Common Errors (And How to Fix Them)
❌ My model doesn't appear in the admin
You never registered it, so the admin doesn't know it exists.
✅ Fix: add admin.site.register(YourModel) (or the @admin.register decorator) in the app's admin.py.
❌ I can't log in to /admin/
No administrator account exists yet, or you forgot the password.
✅ Fix: run python manage.py createsuperuser to make an account (after migrate).
❌ The admin page itself won't load (404 or no apps)
Your app isn't installed, so its models and migrations are ignored.
✅ Fix: add your app to INSTALLED_APPS in settings.py, then run migrate.
📋 Quick Reference
| Command / Option | What It Does |
|---|---|
| python manage.py createsuperuser | Create an admin account you can log in with |
| admin.site.register(Post) | Make the Post model appear in the admin |
| @admin.register(Post) | Register a model with a custom ModelAdmin class |
| list_display | Choose which columns show in the list view |
| search_fields | Add a search box over the named fields |
🏆 Mini Challenge: Build a ModelAdmin Config
Write a helper that takes a list of fields and prints a ready-to-paste list_display line for a ModelAdmin class.
# 🏆 Mini Challenge: generate a list_display configuration line.
def build_list_display(fields):
# Wrap each field in quotes and join into a tuple
quoted = ", ".join(f'"{field}"' for field in fields)
return f" list_display = ({quoted})"
columns = ["title", "author", "published"]
print("class PostAdmin(admin.ModelAdmin):")
print(build_list_display(columns))
# EXPECTED:
# class PostAdmin(admin.ModelAdmin):
# list_display = ("title", "author", "published")❓ Frequently Asked Questions
Lesson complete — you can manage data through the admin!
You enabled the admin, created a superuser, registered a model so it appears in the interface, and customised the list view with a ModelAdmin class using list_display, list_filter, search_fields, and prepopulated_fields.
Practice quiz
How do you create an administrator account for the admin?
- python manage.py runserver
- python manage.py createsuperuser
- python manage.py migrate
- python manage.py startadmin
Answer: python manage.py createsuperuser. createsuperuser prompts for a username, email, and password and creates a full-permission account.
Which call registers the Post model so it appears in the admin?
- admin.site.register(Post)
- admin.add(Post)
- Post.register()
- site.install(Post)
Answer: admin.site.register(Post). admin.site.register(Post) adds the model to the admin so it gets auto-generated CRUD pages.
Which decorator registers a model with a custom ModelAdmin class?
- @admin.site
- @register.model
- @admin.register(Post)
- @modeladmin(Post)
Answer: @admin.register(Post). @admin.register(Post) above a ModelAdmin subclass registers the model with that customisation.
Which ModelAdmin option chooses the columns shown in the list view?
- search_fields
- list_filter
- prepopulated_fields
- list_display
Answer: list_display. list_display is a tuple of field names that become the columns in the change list.
What must you run before createsuperuser so the auth tables exist?
- collectstatic
- migrate
- makemigrations only
- test
Answer: migrate. The superuser is stored in auth_user, so you must run migrate first to create the tables.
Which ModelAdmin option adds a search box over named fields?
- list_display
- list_filter
- search_fields
- ordering
Answer: search_fields. search_fields is a tuple of fields the admin search box queries.
Why might your model not appear in the admin?
- You never registered it
- You ran migrate twice
- You created a superuser
- You used ModelAdmin
Answer: You never registered it. A model only appears after admin.site.register or the @admin.register decorator.
Which option auto-fills a slug field from the title?
- list_display
- list_filter
- search_fields
- prepopulated_fields
Answer: prepopulated_fields. prepopulated_fields = {'slug': ('title',)} auto-fills the slug from the title as you type.
What controls the label shown for each row in the admin list?
- The model's id
- The first CharField
- The model's __str__ method
- list_filter
Answer: The model's __str__ method. The __str__ method gives each object a readable name in the admin.
Which ModelAdmin option adds a filter sidebar?
- search_fields
- list_filter
- list_display
- prepopulated_fields
Answer: list_filter. list_filter adds a sidebar of filters for the named fields.
Continue this course
- Previous: Static Files
- Next: Models & Migrations — Define your database schema in Python and evolve it safely with migrations
- Quick reference: Django cheat sheet › Admin & Auth
Frequently asked questions
What is the Django admin?
The Django admin is a built-in, automatically generated web interface for managing your application's data. Once you register a model, Django creates fully working pages to list, add, edit, and delete rows in that model's database table — all rendered in the browser with no extra code. It is meant for trusted site administrators and content editors, not for end users of your public site.
How do I create a superuser for the Django admin?
Run 'python manage.py createsuperuser' in your terminal. Django will prompt you for a username, an email address, and a password. The account it creates has full permissions, so you can log in at /admin/ and manage every registered model. You must run migrations first, because the admin and authentication tables need to exist in the database before a superuser can be saved.
Why doesn't my model show up in the admin?
The most common reason is that you never registered it. A model only appears in the admin after you call admin.site.register(YourModel) — or use the @admin.register(YourModel) decorator — inside the app's admin.py file. Also confirm that the app is listed in INSTALLED_APPS and that you have run your migrations so the table actually exists.
Can I customise how the admin looks and behaves?
Yes. You create a ModelAdmin subclass and register it alongside your model. On that class you can set options like list_display to choose which columns appear in the list view, list_filter to add sidebar filters, search_fields to add a search box, and prepopulated_fields to auto-fill a slug from another field. This lets you tailor the admin to how your editors actually work.