| name | admin-interface |
| description | Configure Django admin with Unfold and SiteAwareModelAdmin. Use when creating/modifying admin classes, working with inlines, or when the user mentions admin interface. |
| allowed-tools | Read, Grep, Glob |
Admin Interface
Django Unfold
Use Unfold instead of default Django admin for all ModelAdmin classes.
from unfold.admin import ModelAdmin, TabularInline
@admin.register(MyModel)
class MyModelAdmin(ModelAdmin):
...
Use Unfold inlines:
from unfold.admin import TabularInline, StackedInline
Site-Aware Models
All site-aware models MUST use SiteAwareModelAdmin:
from freedom_ls.site_aware_models.admin import SiteAwareModelAdmin
@admin.register(Topic)
class TopicAdmin(SiteAwareModelAdmin):
list_display = ("title", "subtitle")
What it does:
- Automatically excludes
site field from forms
- Inherits from
unfold.admin.ModelAdmin
Location: freedom_ls/site_aware_models/admin.py
Rule: Never display or allow editing of site field in admin
django-guardian (Object Permissions)
For models requiring object-level permissions:
from guardian.admin import GuardedModelAdmin
@admin.register(Cohort)
class CohortAdmin(GuardedModelAdmin):
list_display = ["name"]
search_fields = ["name"]
exclude = ["site"]
Note: GuardedModelAdmin does NOT inherit from SiteAwareModelAdmin, so you must manually exclude = ["site"] for site-aware models.
Common Patterns
Basic Admin
@admin.register(Model)
class ModelAdmin(SiteAwareModelAdmin):
list_display = ("field1", "field2")
search_fields = ("field1", "field2__related")
list_filter = ("category", "created_at")
readonly_fields = ("slug", "created_at")
exclude = ["site"]
With Inlines
from unfold.admin import TabularInline
class ChildInline(TabularInline):
model = Child
extra = 0
fields = ("field1", "field2")
autocomplete_fields = ["foreign_key"]
@admin.register(Parent)
class ParentAdmin(SiteAwareModelAdmin):
inlines = [ChildInline]
With Fieldsets
@admin.register(Model)
class ModelAdmin(SiteAwareModelAdmin):
fieldsets = (
(None, {"fields": ("title", "description")}),
("Metadata", {
"fields": ("meta", "tags"),
"classes": ("collapse",)
}),
)
Custom Display Methods
@admin.register(Student)
class StudentAdmin(SiteAwareModelAdmin):
list_display = ["get_full_name", "get_email"]
def get_full_name(self, obj):
return f"{obj.user.first_name} {obj.user.last_name}".strip()
get_full_name.short_description = "Full Name"
get_full_name.admin_order_field = "user__first_name"
Key Rules
- Always use
SiteAwareModelAdmin for site-aware models
- Never expose
site field in admin interface
- Use Unfold inlines not Django's admin inlines
- Use
autocomplete_fields for ForeignKey/M2M to avoid loading all options
- Use
readonly_fields for auto-generated fields (slug, timestamps)
- Use
fieldsets to organize complex forms