Unfold implements special functionality for handling expandable rows in changelists called sections. Once the list_sections
attribute is configured, rows in the changelist will display an arrow button at the beginning of the row which can be used to show additional content.
The list_sections
attribute consists of Python classes inheriting from TableSection
or TemplateSection
defined in unfold.sections
. These classes are responsible for rendering the content in the expandable area.
from unfold.admin import ModelAdmin
from unfold.sections import TableSection, TemplateSection
from .models import SomeModel
# Table for related records
class CustomTableSection(TableSection):
verbose_name = _("Table title") # Displays custom table title
height = 300 # Force the table height. Ideal for large amount of records
related_name = "related_name_set" # Related model field name
fields = ["pk", "title", "custom_field"] # Fields from related model
# Custom field
def custom_field(self, instance):
return instance.pk
# Simple template with custom content
class CardSection(TemplateSection):
template_name = "your_app/some_template.html"
@admin.register(SomeModel)
class SomeAdmin(ModelAdmin):
list_sections = [
CardSection,
CustomTableSection,
]
When it comes to classes inheriting from TableSection
, you may find a problem with an extraordinary amount of queries executed on changelist pages. This problem has two parts:
TableSection
works with related fields so another query is required to obtain data from the related tableThe easiest solution for this issue is to configure pagination to a smaller amount of records by setting list_per_page = 20
. While this solution might work for you, it is not optimal.
The optimal solution is using prefetch_related
:
get_queryset
and use prefetch_related
on all related rows until you don't have any duplicated SQL queries in django-debug-toolbar outputfrom unfold.admin import ModelAdmin
from .models import SomeModel
@admin.register(SomeModel)
class SomeAdmin(ModelAdmin):
list_per_page = 20 # Quick solution
list_sections = [CustomTableSection]
# Custom queryset prefetching related records
def get_queryset(self, request):
return (
super()
.get_queryset(request)
.prefetch_related(
"related_field_set",
"related_field__another_related_field",
"related_field__another_related_field__even_more_related_field",
)
)
Unfold supports multiple related tables in expandable rows. Specify a section class for each related field and put them into list_sections
. For each class, you can add a verbose_name
to display a custom title right above the table to distinguish between different related fields.
from unfold.admin import ModelAdmin
from .models import SomeModel
@admin.register(SomeModel)
class SomeAdmin(ModelAdmin):
list_sections = [
CustomTableSection, OtherCustomTable
]
© 2023 - 2025 Created by unfoldadmin.com. All rights reserved.