如何在Django管理员中实现全局隐式过滤器?

时间:2011-03-17 20:02:09

标签: django filter admin permanent

我的很多模型都有“公司”模型的外键。每个登录用户都可以是一个或多个公司的一部分(User m2m Company,not null)。

我希望当前的管理员用户在管理员索引页面上打开“公司护目镜”,即选择列表,或者可以在基本标题中打开他们的“当前”公司。这样做应该自动应用“公司等于”过滤器 - 对于具有公司外键的模型 - 以及任何其他过滤器。

实现这一目标的最佳方式是什么?

注意:这是管理界面的舒适功能,在这个阶段不需要实际的模型保护(客户端视图确实需要,但我可以使用自定义管理器并通过request.user查找)。

我目前的想法是:

  1. 将当前公司存储在会话中。

  2. 使用中间件从会话中查找当前公司,并将公司附加到所有相关链接:

    a)change_list :(?/&)“company__eq = 42”

    b)对于拥有公司外键的模型,change_view“add?company = 42”。

    这可能需要反转或模式匹配URL以找出他们的模型并检查它是否存在外键(或者我可能事先准备好该列表以提高性能)。

  3. 在每个ModelAdmin表单中包含外键字段,但通过CSS隐藏它,以便change_view add(“new”)包含链接中的预设外键值而不提及它。

  4. 您认为这是一种可行的方法吗?

    如果http://code.djangoproject.com/ticket/10761已实现,我想我可以指定一个自定义查询集,从request.session读取当前公司并完成它。也许更好地快速跟踪(=制作并提交补丁)该票证?

    编辑:或者只是在每个需要它/有外键的ModelAdmin上重新定义queryset()方法?

2 个答案:

答案 0 :(得分:3)

我的投票是覆盖ModelAdmin.queryset,因为您可以方便地访问该请求。为第3点覆盖save_model

 class MyModelAdmin(admin.ModelAdmin):
    def queryset(self, request):
        qs = super(MyModelAdmin, self).queryset(request)
        if request.session.get('company_goggles'):
             return qs.filter(company=request.session['company_goggles'])
        return qs

如果您有许多模型,我会将ModelAdmin子类化为GogglesAdmin,并定义一个字段/默认值以从中提取字段名称以及预先自动注入公司。

class CompanyGogglesAdmin(admin.ModelAdmin):
    def queryset(self, request):
        qs = super(CompanyGoggleAdmin, self).queryset(request)
        if request.session.get('company_goggles'):
            return qs.filter(**{ getattr(self, 'company_field', 'company') : 
                          request.session['company_goggles'] })

顺便说一下,我真的很喜欢这个“公司护目镜”的术语。

答案 1 :(得分:1)

要回答最后一个问题:如果您只想显示查询集的某些项,则可以覆盖ModelAdmin的{​​{1}}方法。例如,如果您在当前会话中设置了公司。您还可以覆盖queryset()方法,让save_model() company在保存表单时始终指向用户的公司:

ForeignKey