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

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

问题描述

很多我的模型都有一个公司模式的外键。每个登录用户都可以是一个或多个公司的一部分(用户m2m公司,不为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)包括


你觉得这是一个可行的方法吗? >

如果 http://code.djangoproject.com/ticket/ 10761 被执行,我想我可以指定一个自定义查询器,它从request.session读取当前的公司,并完成它。或者可能只需要在需要它的每个ModelAdmin上重新定义一个queryset()方法,有外键?

解决方案

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

  class MyModelAdmin(admin.ModelAdmin) :
def queryset(self,request):
qs = super(MyModelAdmin,self).queryset(request)
如果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)
如果request.session.get('company_goggles'):
return qs.filter(** {getattr(self,'company_field','company' ):
request.session ['company_goggles']})

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


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?

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).

My current idea is:

  1. Store current company in session.

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

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

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

    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).

  3. 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?

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?

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

解决方案

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

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管理员中实现全局隐式过滤器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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