如何在 Django admin 中实现全局隐式过滤器? [英] How can I implement a global, implicit filter in Django admin?

查看:12
本文介绍了如何在 Django admin 中实现全局隐式过滤器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的很多模型都有一个指向公司"模型的外键.每个登录用户都可以是一个或多个公司的一部分(用户 m2m 公司,不为空).

A lot of my models have a foreign key to a "Company" model. Every logged in user can be part of one or more companies (User m2m Company, not null).

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

I would like the current admin user to have "Company goggles" on, i.e. a select list, on the admin index page or maybe the base header, where they can switch their "current" Company. Doing that should automatically apply a "company equals" filter - for models that have a foreign key to Company - in addition to any other filters.

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

What's the best way to achieve this?

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

NB: This is meant as a comfort function for the admin interface, actual protection of models is not necessary at this stage (client views do need that but I can just use a custom Manager and lookup via request.user there).

我目前的想法是:

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

  1. Store current company in session.

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

Use middleware to look up current company from session, and append the company to all relevant links:

a) change_list: (?/&)"company__eq=42"

a) change_list: (?/&)"company__eq=42"

b) 对于具有 Company 外键的模型,change_view "add?company=42".

b) change_view "add?company=42" for models that have a foreign key to Company.

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

This may require to reverse or pattern match the URLs to find out their model and check it for presence of the foreign key (or I might prepare that list beforehand to improve performance).

在每个 ModelAdmin 表单中包含外键字段,但通过 CSS 将其隐藏,以便 change_view add ("new") 包含来自链接的预设外键值,而无需提及.

Include in each ModelAdmin form the foreign key field, but hide it via CSS, so that change_view add ("new") includes the preset foreign key value from the link without mentioning it.

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

Do you find this a viable approach?

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

If http://code.djangoproject.com/ticket/10761 was implemented I guess I could just specify a custom queryset which reads the current company from request.session and be done with it. Maybe better to fast-track (=make and submit patch) that ticket instead?

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

or maybe just redefine the queryset() method on every ModelAdmin that needs it / has the foreign key?

推荐答案

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

My vote is is for overriding ModelAdmin.queryset, since you conveniently have access to the request there. Override save_model for point 3.

 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 的东西,并定义一个字段/默认值来从中提取字段名,以及预先保存的自动公司注资.

If you have many models, I'd subclass ModelAdmin as something like GogglesAdmin and define a field / default to pull the fieldname from and also the pre-save auto injecting of company.

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'] })

顺便说一句,我真的很喜欢公司护目镜"这个术语.

By the way, I really like this "company goggles" terminology.

这篇关于如何在 Django admin 中实现全局隐式过滤器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆