使用包含 RadioSelect 小部件的 ModelChoiceField 在 ModelForm 的查询集中获取 request.user
Posted
技术标签:
【中文标题】使用包含 RadioSelect 小部件的 ModelChoiceField 在 ModelForm 的查询集中获取 request.user【英文标题】:Get request.user in queryset in a ModelForm with a ModelChoiceField that contains a RadioSelect widget 【发布时间】:2015-10-09 15:55:06 【问题描述】:关于将request.user
传递给ModelForm
中的queryset
,我想向社区提出以下问题。我的ModelForm
是:
class goForm(ModelForm):
user_choice = goModelChoiceField(
widget=forms.Radioselect,
queryset=Document.objects.all().filter(who_upload=request.user),
empty_label=None,
to_field_name='docfile',
label = 'Please select'
)
class Meta:
model = go
fields = ['user_choice']
与
class goModelChoiceField(forms.ModelChoiceField):
def label_from_instance(self, obj):
return "'%s' uploaded on %s" % (obj.file_name,
obj.when_upload.date())
我找到的所有答案都是指将request.user
传递给__init__
或使用过滤后的选择填充视图中的goForm
。但是,在我的情况下似乎没有任何效果,因为我已经对表单进行了子类化以返回特定的字符串,而且我正在使用
RadioSelect
小部件特别需要 queryset
作为参数(我对此不是 100% 确定)。那么如何在user_choice
中传递request.user
呢?
【问题讨论】:
在__init__
中执行此操作是完全正确的解决方案,您拥有自定义类这一事实无关紧要。请展示您尝试过的内容以及遇到的错误。
请检查您的代码的缩进。将 goModelChoiceField
放在 ModelForm 中可能是个坏主意(它会使代码混乱并阻止您在其他类中重用它)。在goModelChoiceField
中定义user_choice
肯定是错误的。
@Alasdair :是的,我意识到,我将user_choice
移到goModelChoiceForm
之外和Meta
类中。奇怪的是它是如何以两种方式工作的。谢谢。
user_choice
字段也不应该在 Meta 类中定义。
不,如果它在 Meta 中,它根本不起作用:Django 不希望在那里定义字段。你应该将 goModelChoiceField 变成一个独立的类;嵌套类在 Python 中没有任何好处。这些事情都不会影响你如何通过request.user
,这仍然需要在__init__
中完成。
【参考方案1】:
model choice field docs 展示了如何在__init__
方法中设置查询集。
class goForm(ModelForm):
user_choice = goModelChoiceField(
widget=forms.RadioSelect,
queryset=None,
empty_label=None,
to_field_name='docfile',
label = 'Please select'
)
def __init__(self, user, *args, **kwargs):
super(goForm, self).__init__(*args, **kwargs)
self.fields['user_choice'].queryset = Document.objects.all().filter(who_upload=user)
class Meta:
model = go
fields = ['user_choice']
请注意,__init__
方法现在将用户作为参数,因此请记住在视图中实例化表单的任何位置传递它。例如:
form = goForm(user=request.user, data=request.POST)
【讨论】:
很高兴它对你有用。最后一点建议 - 我建议将模型重命名为Go
,将表单重命名为 GoForm
等。Django 模型通常大写,小写形式用于单个实例,例如 go = Go.objects.get(id=10)
。
非常感谢Alasdair
。如果我可以问另一个问题。您的解决方案虽然在有 GET 时似乎渲染得很好,但是当有 POST 时,当参数序列是您在解决方案中给出的序列时,它要么给出non-keyword arg after keyword arg
(即:(user=request.user,data =request.POST)` 并通过交换订单给出__init__() got multiple values for keyword argument 'user'
。我怀疑我应该保留第一个订单,但我怎样才能避免这个错误?再次感谢Alasdair
。
看来上面的解决方案不是改变__init__
的签名而是用user = kwargs.pop('user', None)
得到user
(参考this),这就是为什么我编辑了你的答案。
您可以通过在 __init__
签名中包含用户或从 kwargs 中弹出它来使代码正常工作。如果您将所有参数都作为关键字参数提供,您不应该在我的代码中获得 non-keyword arg after keyword arg
。以上是关于使用包含 RadioSelect 小部件的 ModelChoiceField 在 ModelForm 的查询集中获取 request.user的主要内容,如果未能解决你的问题,请参考以下文章
如何将 CSS 类添加到 django RadioSelect 标签?