Итак, я смог решить свою проблему. Для тех, кто может столкнуться с подобной ситуацией, вот шаги:
Подход, который я выбрал, состоит в том, чтобы изменить шаблон change_list.html и вручную отфильтровать элементы, которые я не хотел включать. Впрочем, нужно внести целый ряд изменений.
Сначала добавьте метод changelist_view
в ModelAdmin:
# myproject/account/admin.py
class StaffUserAdmin(models.ModelAdmin):
...
def changelist_view(self, request, extra_context=None):
groups = Group.objects.exclude(name__in=['Press',]).values_list('name')
extra_context = {
'groups': [x[0] for x in groups],
}
return super(StaffUserAdmin, self).changelist_view(request,
extra_context=extra_context)
По сути, все, что мы здесь делаем, это передаем отфильтрованный список групп, которые мы хотим использовать, в контекст для шаблона.
Во-вторых, создайте шаблон change_list.html для своего приложения.
# myproject/templates/admin/auth/staffuser/change_list.html
{% extends "admin/change_list.html" %}
{% load admin_list %}
{% load i18n %}
{% load account_admin %}
{% block filters %}
{% if cl.has_filters %}
<div id="changelist-filter">
<h2>{% trans 'Filter' %}</h2>
{% for spec in cl.filter_specs %}
{% ifequal spec.title 'group' %}
{% admin_list_group_filter cl spec groups %}
{% else %}
{% admin_list_filter cl spec %}
{% endifequal %}
{% endfor %}
</div>
{% endif %}
{% endblock filters %}
Этот заслуживает небольшого объяснения. Сначала загружается тег шаблона: admin_list
используется для стандартного тега шаблона Django, отвечающего за рендеринг фильтров, admin_list_filter
, i18n
используется для trans
, а account_admin
для моего пользовательского тега шаблона (обсуждено в секунду) admin_list_group_filter
.
Переменная spec.title
содержит заголовок фильтруемого поля. Поскольку я пытаюсь изменить способ отображения фильтра групп, я проверяю, равен ли он «группам». Если это так, то я использую свой пользовательский тег шаблона, в противном случае он возвращается к стандартному тегу шаблона Django.
В-третьих, мы создаем тег шаблона. Я просто скопировал тег шаблона Django по умолчанию и внес необходимые изменения.
# myproject/account/templatetags/account_admin.py
from django.template import Library
register = Library()
def admin_list_group_filter(cl, spec, groups):
return {'title': spec.title, 'choices' : list(spec.choices(cl)), 'groups': groups }
admin_list_group_filter = register.inclusion_tag('admin/auth/group_filter.html')(admin_list_group_filter)
Единственное, что я здесь изменил, - это добавление нового аргумента в метод, называемый «группы», чтобы я мог передать отфильтрованный список групп ранее, а также добавление нового ключа в словарь для передачи этого список в контексте для тега шаблона. Я также изменил шаблон, используемый тегом, на новый, который мы собираемся создать.
В-четвертых, создайте шаблон для тега шаблона.
# myproject/templates/admin/auth/group_filter.html
{% load i18n %}
<h3>{% blocktrans with title as filter_title %} By {{ filter_title }} {% endblocktrans %}</h3>
<ul>
{% for choice in choices %}
{% if choice.display in groups %}
<li{% if choice.selected %} class="selected"{% endif %}>
<a href="{{ choice.query_string|iriencode }}">{{ choice.display }}</a></li>
{% endif %}
{% endfor %}
</ul>
Здесь нет больших сюрпризов. Все, что мы делаем, это собираем все кусочки вместе. Каждый choice
представляет собой словарь со всеми значениями, необходимыми для построения ссылки фильтра. В частности, choice.display
содержит фактическое имя экземпляра, по которому будет выполняться фильтрация. Очевидно, я настроил проверку, чтобы увидеть, есть ли это значение в моем фильтрованном списке групп, которые я хочу показать, и отображать ссылку, только если она есть.
Итак, это немного запутанно, но работает замечательно хорошо. Точно так же у вас есть список фильтров, который вам нужен, а не фильтры по умолчанию, сгенерированные Django.