Search⌘ K
AI Features

Implementing Search and Related Lookups

Explore how to implement effective search and related lookups in Django admin. Understand the use of list_filter for direct and related fields, and search_fields for free-text queries. Learn how to traverse model relationships with double-underscore syntax to create powerful filters. This lesson equips you to enhance data discovery and navigation in large admin datasets without custom queries.

As your database grows from dozens of records to tens of thousands, simple pagination is no longer enough to navigate the changelist. Users need precise tools to slice through massive datasets to find specific entries. We must equip our administration panels with targeted filters and robust search capabilities, ensuring that locating a specific record takes seconds rather than minutes.

Configuring direct field filters

The Django admin provides a built-in filtering sidebar that we activate using the list_filter attribute. This sidebar allows users to drill down into the dataset by clicking categorical options. It is highly effective for dates, booleans, categorical choices, and direct foreign keys.

To see this in action, we will configure the QuestionAdmin to allow filtering by its publish date and the author who wrote it.

import os
import random
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "helloworld.settings")

import django
django.setup()

from faker import Faker
from model_bakery import baker
from datetime import timezone
from sample_app.models import Author, Question, Choice

fake = Faker()

def generate_data():
    for _ in range(100):
        author_name = "" if random.random() < 0.1 else fake.name()
        
        author = baker.make(
            Author,
            name=author_name,
        )
        
        question = baker.make(
            Question,
            ref_author=author,
            question_text=fake.sentence(nb_words=6),
            pub_date=fake.date_time_between(start_date="-30d", end_date="now", tzinfo=timezone.utc),
        )
        
        baker.make(
            Choice,
            question=question,
            choice_text=fake.word(),
            votes=fake.random_int(min=0, max=100),
        )

if __name__ == '__main__':
    generate_data()
Activating the filtering sidebar on the Question changelist
  • Line 17: We add the ...