Python 对于在另一个模型上定义了关系的模型,是否可以在Django admin中限制筛选多个/外键?
所以这个标题有点迟钝,我知道,但我想不出更简洁的方式来表达它。问题是: 我为“用户类型”创建了两个代理模型,它们都继承自django.contrib.auth.user。每个都有一个自定义管理器,将查询集限制为属于特定组的项。具体来说,有一个PressUser是属于“Press”组的任何用户,还有一个StaffUser是除“Press”之外的任何其他组中的任何用户 问题是,当我在StaffUsers modeladmin上添加“组”以列出过滤器时,生成的过滤器选项是每个可用组,包括“按”,而不仅仅是StaffUsers可用的组 我在网上做了一些研究,提出了一个定制的filterspec,可以产生我想要的行为,但问题是用户模型的“groups”属性实际上是从组模型中应用的一个相关名称。因此,我无法将filterspec附加到代理模型中的“组”Python 对于在另一个模型上定义了关系的模型,是否可以在Django admin中限制筛选多个/外键?,python,django,django-admin,django-admin-filters,Python,Django,Django Admin,Django Admin Filters,所以这个标题有点迟钝,我知道,但我想不出更简洁的方式来表达它。问题是: 我为“用户类型”创建了两个代理模型,它们都继承自django.contrib.auth.user。每个都有一个自定义管理器,将查询集限制为属于特定组的项。具体来说,有一个PressUser是属于“Press”组的任何用户,还有一个StaffUser是除“Press”之外的任何其他组中的任何用户 问题是,当我在StaffUsers modeladmin上添加“组”以列出过滤器时,生成的过滤器选项是每个可用组,包括“按”,而不仅
是否有其他方法应用过滤器规格?或者,是否有更好的方法来过滤默认过滤器spec返回的项目?因此,我能够解决自己的问题。对于那些可能遇到类似情况的人,以下是步骤: 我采取的方法是修改change_list.html模板并手动过滤掉我不想包含的项目。不过,有相当多的变化要做 首先,将
changelist\u视图
方法添加到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 %}
我在这里所做的唯一更改是向名为“groups”的方法添加一个新参数,这样我就可以传入以前过滤过的组列表,以及向字典添加一个新键,以便将该列表传递到模板标记的上下文中。我还将标签使用的模板更改为我们即将创建的新模板
第四,为模板标签创建模板
# 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>
#myproject/templates/admin/auth/group_filter.html
{%load i18n%}
{{filter_title}}{%endblocktrans%}使用标题作为筛选器的{%blocktrans%}
{choices%%中的选项为%s}
{%if choice.display in groups%}
{%endif%}
{%endfor%}
这里没有什么大的惊喜。我们所做的就是把所有的部分放在一起。每个选项
都是一个字典,包含构建筛选器链接所需的所有值。具体来说,choice.display
保存将被筛选的实例的实际名称。很明显,我已经设置了一个检查,以查看该值是否在我要显示的组的筛选列表中,并且仅在该值存在时渲染链接
所以,它有点复杂,但效果非常好。就像那样,您有一个过滤器列表,它正是您想要的,而不是Django生成的默认过滤器。我要马上告诉您,我以前从未做过这件事,所以请恕我直言 我的建议是重写
ModelAdmin
,返回一个自定义ChangeList
类,您可以在admin
模块中的某个地方定义该类
您的自定义ChangeList
类将简单地重写,因此您可以为组
字段映射自定义的FilterSpec
您可能感兴趣的另一件事是来自指定自定义过滤器规格的功能请求的补丁。尽管@bendavis78最近发布他正在开发一个新的补丁,但最新的补丁对Django 1.3rc1还不起作用,但取决于你的Django版本,它可能会完全适用
看起来它几乎没有错过进入1.3里程碑的机会,所以我认为它将在Django 1.4上工作后尽快进入主干。+1,将过滤后的组推到
额外上下文中
是一种巧妙的做法,谢谢。我没有考虑过这种方法。是的,我在搜索中偶然发现了那张票。没有什么比意识到问题的解决方案是存在的更让人恼火的了,但它还不能使用。我可能会回去尝试你的建议,但现在我已经让它发挥作用了(尽管可能没有那么优雅),我很犹豫是否要再次使用它。
# 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>