我希望做这样的事情:
Model limit_choices_to={'user': user}
有一些差异。
有些型号可能会解释:
class Job(models.Model):
name = models.CharField(max_length=200)
operators = models.ManyToManyField(User)
class Activity(models.Model):
job = models.ForeignKey(Job)
job_operators = models.ManyToManyField(User, limit_choices_to={user: Job.operators} blank=True, null=True)
注意:语法并非旨在纠正,而是说明性的。
现在,我在使用中间件获取当前用户方面取得了一些成功,因为SO描述了一些答案,但是,我希望我可以通过request.POST获取当前的Job,这样,如果保存了活动,我将能够识别当前的作业,因此,作为运算符的用户子集将成为用户可以在活动模型中进行选择。
换句话说,根据父字段中ManyToManyField的选择,将子选择提供给子字段,或者,如果John,Jim,Jordan和Jesse在Job上工作,则只选择那些名称到描述一项活动的工作,在该工作内部并归因于该工作。
顺便说一下,这是我对中间件的天真尝试:# threadlocals middleware
try:
from threading import local
except ImportError:
from django.utils._threading_local import local
_thread_locals = local()
def get_current_user():
return getattr(_thread_locals, 'user', None)
def get_current_job():
return getattr(_thread_locals, 'job', None)
class ThreadLocals(object):
"""Middleware that gets various objects from the
request object and saves them in thread local storage."""
def process_request(self, request):
_thread_locals.user = getattr(request, 'user', None)
_thread_locals.job = getattr(request.POST["job"], 'job', None)
和活动模型:
operators = modes.ManyToManyField(User, limit_choices_to=dict(Q(User.objects.filter(job==threadlocals.get_current_job)))
谢谢。
答案 0 :(得分:2)
好吧,我讨厌在你的作品中扔一把猴子扳手,但你真的不需要使用threadlocals hacks。
用户位于请求对象中,这意味着无需使用中间件提取它。它作为参数传递给每个视图。
限制表单选择的技巧是动态更改表单中使用的查询集,而不是在模型中进行限制选择。
所以你的表格看起来像这样:
# forms.py
from django import forms
from project.app.models import Activity
class ActivityForm(forms.ModelForm):
class Meta:
model Activity
,您的观点将如下所示:
# views.py
...
form = ActivityForm(instance=foo)
form.fields['job_operators'].queryset = \
User.objects.filter(operators__set=bar)
...
这只是一个快速草图,但应该给你一般的想法。
如果您想知道如何在管理员中避免使用threadlocals,请阅读James Bennett撰写的Users and the admin。
Collin Grady的编辑 Useful form tricks in Django还显示了一个以__init__形式动态设置查询集的示例,该方法比上面的示例更清晰。
答案 1 :(得分:2)
但是你用list_filter定义的字段呢?他们只尊重limit_choices_to。因此,如果您想限制Django Admin过滤器的选择,您必须使用limit_choices_to和一些中间件来根据当前用户过滤它们。或者是否有更简单的解决方案?
答案 2 :(得分:0)
Monkey Wrenches欢迎朋友!
我也找到了另一种方式,虽然看起来不那么直接:
class ActivityForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(ActivityForm, self).__init__(*args, **kwargs)
if self.initial['job_record']:
jr = JobRecord.objects.get(pk=self.initial['job_record'])
self.fields['operators'].queryset = jr.operators
class Meta:
model = Activity
exclude = ('duration',)
我认为你的方式更好!谢谢你!