Django Admin as a Fast, Ready-Made Manual Entry Tool

Personal Catalogue: Django & PostgreSQL

Chapter 3 · Django Admin as a Fast, Ready-Made Manual Entry Tool

Chapter 2 built the real schema — Item, ItemType, and Tag — and ran it against a live PostgreSQL database. This chapter gets a genuinely working data-entry interface on top of that schema without writing a single HTML form by hand, using the one real feature that makes this variant of the project move fastest: Django's own built-in admin.

Why the Admin Is the Right Fast-Entry Tool Here

This project's own real deadline means a working way to actually add items matters more, in the short term, than a polished public-facing add-item page. Django generates a complete, permission-gated CRUD interface directly from a model class — list views, detail/edit forms, delete confirmation, and real field-type-aware widgets (a dropdown for the item_type foreign key, a proper multi-select for the tags many-to-many) — for the cost of a handful of lines in admin.py. This isn't a shortcut around building a real app; it's genuinely the fastest correct way to get a real, working manual-entry tool live today, with the custom public-facing form (Chapter 5) built afterward once the core schema is proven out.

Creating a Superuser

The admin requires a real, privileged account to log into:

python manage.py createsuperuser

Follow the real prompts for a username, email, and password. This account is separate from anything this project's own Item/ItemType/Tag models define — it's part of Django's own built-in auth app, already migrated in Chapter 1's own first migrate run.

Registering the Models

A bare-minimum registration already produces a working, if plain, admin interface:

# catalogue/admin.py from django.contrib import admin from .models import Item, ItemType, Tag admin.site.register(Item) admin.site.register(ItemType) admin.site.register(Tag)

Run the development server and visit /admin/ to confirm all three models genuinely show up, each with a working add/list/edit/delete interface already functioning against the real PostgreSQL database.

A Real, Customized ModelAdmin

The bare registration works, but a few genuinely small customizations make the admin dramatically more useful for this project's own real day-to-day task — quickly checking whether an item already exists before adding a new one:

@admin.register(Item) class ItemAdmin(admin.ModelAdmin): list_display = ('title', 'item_type', 'creator', 'release_year', 'created_at') list_filter = ('item_type', 'tags') search_fields = ('title', 'creator') filter_horizontal = ('tags',)
  • list_display — shows title, type, creator, year, and date added right on the list page, instead of the model's own bare __str__ only.
  • list_filter — adds a real sidebar to filter the list by item type or by tag with a single click.
  • search_fields — adds a real search box across title and creator, directly supporting this project's own core "do I already own this?" question.
  • filter_horizontal — replaces the tags field's own default cramped multi-select box with a real, genuinely usable two-column widget for adding and removing tags.
filter_horizontal Specifically for Many-to-Many Fields
Without filter_horizontal, Django's own default widget for a ManyToManyField is a plain multi-select box — usable, but genuinely awkward once the tag list grows past a handful of entries. filter_horizontal is specifically designed for exactly this case: two side-by-side boxes (available tags, selected tags) with a real search filter and add/remove buttons, which is why it's called out here rather than left at Django's own default.
The Real Payoff of Chapter 1's Own Scaffolding
Chapter 1 noted that Django's own project scaffolding was real, genuine setup work the PHP variant of this project skipped entirely. This chapter is where that investment pays off directly: roughly fifteen lines of admin.py code produce a complete, working, searchable, filterable CRUD interface — something the PHP variant has to build by hand, page by page, across its own Chapters 3 and 4.
The Admin Isn't the Public-Facing App
The admin is a real, genuinely useful internal tool — but it's not meant to be the interface this project ships as its own public-facing catalogue browser, and it should never be exposed carelessly once deployed. Chapter 5 builds a dedicated, public-facing add-item form, and Chapter 9's own deployment coverage returns to locking the admin down properly (a non-default URL, real strong credentials) before this project goes anywhere near the internet.

Trying It Out

With ItemType rows already seeded in Chapter 2, log into /admin/ and add a real item through the UI: pick a type from the dropdown, fill in title/creator/year, and — for a book — attach one or more tags using the new filter_horizontal widget. Confirm the item appears correctly on the list page, with its tags visible via the list_filter sidebar.

Hands-On Exercises

Exercise 1

Create a superuser, register all three models with the customized ItemAdmin from this chapter, and add three real items through the admin — one book (with at least two tags), one CD, and one DVD.

📄 View solution
Exercise 2

Explain what specifically filter_horizontal changes about how tags are edited in the admin, and why that change matters more for this project's tags field than it would for, say, the single-valued item_type field.

📄 View solution
Exercise 3

Explain why relying on the Django admin as this project's own primary way of adding items is a reasonable choice given its real deadline, while also explaining why it can't be the app's own final, shipped solution.

📄 View solution

Chapter 3 Quick Reference

  • createsuperuser — creates the privileged account needed to log into /admin/, part of Django's own built-in auth app
  • admin.site.register() — the minimum needed for a working, if plain, CRUD interface per model
  • ModelAdmin customizationlist_display, list_filter, search_fields, and filter_horizontal turn that plain interface into a genuinely fast day-to-day tool
  • filter_horizontal — specifically improves the default many-to-many widget, replacing a cramped multi-select with a real two-column filterable UI
  • Real limit — the admin is an internal tool, not the public-facing app, and needs locking down before deployment (Chapter 9)
  • Next chapter: Building the Public-Facing Views — the real list and detail pages visitors (i.e., you) will actually browse