Как реализовать разбиение на страницы для фильтров боковой панели администратора Django 5?
Проблема
Фильтры боковой панели администратора Django отображают все параметры без разбивки на страницы, что становится громоздким, когда у вас есть сотни связанных объектов:
By Study
• All
• Study-001: Genetic markers in mice
• Study-002: Effects of caffeine
...
• Study-999: Soil microbiome analysis
При большом количестве опций это делает пользовательский интерфейс непригодным для использования и снижает производительность.
Наш подход
Мы внедрили пользовательские фильтры с разбивкой на страницы, чтобы одновременно отображать только подмножество параметров:
By Study
• All
• Study-001: Genetic markers in mice
• Study-002: Effects of caffeine
...
• Study-010: Plant growth factors
Page 1 of 100 | Next >
Реализация
- Пользовательский класс фильтра:
class StudyListFilter(SimpleListFilter):
title = _('By Study')
parameter_name = 'study__id__exact'
template = 'admin/filter_pagination.html' # Custom template
def lookups(self, request, model_admin):
# Return minimal data - real items are provided in the template
return [('', 'All')]
def queryset(self, request, queryset):
if self.value():
return queryset.filter(study__id=self.value())
return queryset
- Измененный класс администратора:
@admin.register(Assay)
class AssayAdmin(admin.ModelAdmin):
list_filter = (StudyListFilter, 'measurement_type')
change_list_template = 'admin/study_change_list.html'
def changelist_view(self, request, extra_context=None):
extra_context = extra_context or {}
# Get paginated studies
studies = Study.objects.all().order_by('id')
paginator = Paginator(studies, 10)
page_number = request.GET.get('filter_page', 1)
page_obj = paginator.get_page(page_number)
# Pass pagination data to template
extra_context.update({
'filter_page_obj': page_obj,
'filter_items': [(s.id, f"{s.accession_code} - {s.title[:30]}") for s in page_obj],
'filter_name': 'study__id__exact',
'filter_title': 'By Study',
})
return super().changelist_view(request, extra_context)
- Пользовательский шаблон для фильтра:
<h3>{{ title }}</h3>
<ul>
<li {% if not spec.value %}class="selected"{% endif %}>
<a href="?">All</a>
</li>
{% for id, name in filter_items %}
<li {% if spec.value == id|stringformat:'s' %}class="selected"{% endif %}>
<a href="?{{ filter_name }}={{ id }}">{{ name }}</a>
</li>
{% endfor %}
{% if filter_page_obj.has_other_pages %}
<li class="pagination">
{% if filter_page_obj.has_previous %}
<a href="?filter_page={{ filter_page_obj.previous_page_number }}">Previous</a>
{% endif %}
Page {{ filter_page_obj.number }} of {{ filter_page_obj.paginator.num_pages }}
{% if filter_page_obj.has_next %}
<a href="?filter_page={{ filter_page_obj.next_page_number }}">Next</a>
{% endif %}
</li>
{% endif %}
</ul>
Результат
Кнопки для разбивки на страницы отображаются, но не работают.
# The button points to
http://localhost:8000/admin/isa_api/assay/?e=1
Есть ли более простой способ архивировать желаемый результат?