The Django Admin: Instant CRUD for Free

Food Tracker (Django)

Chapter 3 · The Django Admin: Instant CRUD for Free

Chapter 1 promised a working CRUD interface before writing any business logic at all. Here's that promise, delivered.

Registering the Model

# pantry/admin.py from django.contrib import admin from .models import Item admin.site.register(Item)
python manage.py createsuperuser

createsuperuser creates the admin's own login account — a separate concept entirely from any future end-user account this app might have. Visiting /admin/ and signing in with it now shows a complete, working list/add/edit/delete interface for Item, generated from just those two lines of code.

Customizing It With ModelAdmin

Plain registration gives a genuinely functional but generic list view. A ModelAdmin subclass shapes it into something actually useful day to day:

@admin.register(Item) class ItemAdmin(admin.ModelAdmin): list_display = ("name", "category", "status", "expiry_date", "added_at") list_filter = ("status", "category") search_fields = ("name", "barcode") readonly_fields = ("added_at",)
  • list_display — which columns actually show in the list view, instead of just each row's __str__.
  • list_filter — a sidebar of quick filters, genuinely useful for jumping straight to, say, everything with status = "active".
  • search_fields — the admin's own search box, which performs a real substring (SQL LIKE) match by default. Worth flagging honestly: this is a happy coincidence, not the same thing as the live search-as-you-type feature this course builds for the app itself later — the admin's search exists purely for the admin's own list view.
  • readonly_fieldsadded_at is already non-editable (Chapter 2's auto_now_add implicitly sets editable=False), and Django's admin would normally just omit a non-editable field from the form entirely. Listing it in readonly_fields instead keeps its actual value visible — read-only — right there in the change form, rather than making it invisible.

A Real Tool, Not Just a Demo

Before Chapter 4's barcode lookup or Chapter 5's real add-item flow exist, this admin already lets real test Item rows be created by hand — genuinely useful for exercising Chapter 7's expiry query, or Chapter 8's search, against real data long before the app's own user-facing screens are built.

A Real Limit Worth Naming

The admin is a tool for whoever manages the site's data directly — it was never meant to be, and won't become, the pantry app's own end-user interface. There's no camera scanning here, no barcode-triggered lookup, no live search-as-you-type UX. Having a working admin is not the same as having a finished app; the two serve genuinely different audiences.

A genuine, uniquely Django advantage
Food Tracker (FastAPI), Food Tracker (React + Express), and Food Tracker (React + Firebase) would each need real, hand-written code — routes, a UI, or both — just to get this same day-one capability: a basic list/add/edit interface for managing data directly. Here, it exists after two lines in admin.py. This is exactly the "batteries included" tradeoff Chapter 1 named, made concrete rather than abstract.
Going further: list_editable
list_editable = ("status",) lets specific fields be edited directly from the list view itself, without opening the full change form — useful for a quick bulk "mark several as used" pass, once there's real data to try it on.
The admin is only as secure as who can log into it
Once deployed publicly, /admin/ is a powerful, largely unrestricted interface for anyone who successfully logs in — it isn't sandboxed the way the app's own end-user views might be. Real deployment deserves real consideration here: a genuinely strong password, restricting network access to it where feasible, and third-party two-factor packages are all common, real mitigations — treating the admin as purely a development convenience with no real-world exposure risk, once it's live, would be a mistake.

Where This Course Is Headed

Barcode lookup via a Django view, camera-based scanning, the add-item flow via Django Forms, expiry alerts, item history and search, marking items used, recipe lookup, Django REST Framework, deployment, and a capstone.

Hands-On Exercises

Exercise 1

Explain what admin.site.register(Item) alone provides, and what a customized ModelAdmin subclass adds on top of it. Why do list_display, list_filter, and search_fields matter in practice rather than just being nice-to-haves?

📄 View solution
Exercise 2

Explain why readonly_fields is still useful for added_at, given that auto_now_add already makes the field non-editable via editable=False.

📄 View solution
Exercise 3

Explain the real security consideration this chapter raises about exposing /admin/ on a public deployment, and name at least two real mitigations it mentions.

📄 View solution

Chapter 3 Quick Reference

  • admin.site.register(Item) — a full generic CRUD interface, two lines of code
  • ModelAdminlist_display, list_filter, search_fields, readonly_fields shape it into something actually usable
  • The admin's search ≠ the app's own live search — a happy coincidence of substring matching, not the same feature built later
  • A dev tool, not the end-user UI — no camera scanning, no live search UX, a genuinely different audience
  • Real production consideration — a public /admin/ needs a real password policy, restricted access, or 2FA
  • Next chapter: Barcode Lookup: Integrating Open Food Facts