想象一下,我们正在开发一个消息系统,每个Message
都有sender
的外键。
我们正在使用ModelForm
,并且MessageForm
可以从Message
推断其字段。
当然,我们不希望用户通过发布不同的发件人ID 来欺骗sender
。
因此,我们必须从sender
中排除ModelForm
,并在帖子中填写session
。
我应该在何处以及如何将任意数据分配到ModelForm
字段?
在我的示例中,我可能想要访问session
,因此我们也需要访问request
。
这是否意味着代码必须在视图中,就在创建表单之后?
我们如何从代码中分配表单字段并确保它覆盖POST数据?
(当然,这个例子非常虚构,只是为了说明这个问题。)
答案 0 :(得分:1)
只需从sender
中排除ModelForm
字段,当您在POST端点的视图中实例化对象时(保存之前),请确保填充sender
字段使用适当的会话或用户ID。
当您排除该字段时,无法将该字段添加到帖子数据[1],因此用户无法欺骗它。
[1]使用JavaScript,理论上可以添加&sender=someSenderId
,但在您看来,您不需要查找发件人字段。它不会被序列化到ModelForm
对象中。
答案 1 :(得分:1)
您可以按原样排除它,然后在视图中处理表单时执行:
obj = form.save(commit=False)
obj.sender = request.user
obj.save()
或者,您可以在表单的save方法中执行此操作;为此,您需要在表单中暂时保存请求对象。如下所示:
class MyForm(forms.ModelForm):
def __init__(self, request, *args, **kwargs):
self._request = request
super(MyForm, self).__init__(*args, **kwargs)
def save(self, commit=False):
obj = super(MyForm, self).save(commit=False)
obj.sender = self._request.user
if commit:
obj.save()
return obj
我更喜欢第二种方式,因为它有助于将关于该模型的逻辑和它的数据封装在一个整洁的地方。