如何在Django管理员中实现全局隐式过滤器? [英] How can I implement a global, implicit filter in Django admin?
问题描述
我希望当前的管理员用户有公司护目镜 ,即选择列表,在管理员索引页面上,或者也可以是基本标题,可以在其中切换其当前公司。除了任何其他过滤器之外,这样做应该自动应用公司等于过滤器 - 对于具有外部公钥的型号。
什么是最佳实现方式这个?
注意:这是管理界面的舒适功能,在这个阶段实际保护模型是不必要的(客户端视图需要,但我可以只需使用自定义管理器并通过request.user查找)。
我目前的想法是:
-
将当前公司存入会议中。
-
使用中间件从会话中查找当前公司,并将公司附加到所有相关链接:
a)change_list:(?/&)company__eq = 42
b)change_view add?company = 42表示具有外键的模型给公司。
这可能需要反转或模式匹配URL来查找他们的模型并检查它存在外键(或者我可能准备该列表预先提高性能)
-
在每个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:
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"
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).
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屋!