我有一个Django应用程序,用户提交付款订单。显然,安全性很重要。我想尽量减少必须编写的代码量,以避免引入任何安全漏洞并简化维护。使用ModelForm时为某些字段强制执行值
的模式很简单:
class Order(models.Model):
user = models.ForeignKey(User)
created = models.DateTimeField()
paid = models.DateTimeField(null=True, blank=True)
items = models.ManyToManyField(Item)
我使用的是CreateView创造秩序的实例:
class OrderView(CreateView):
model = Order
form_class = OrderForm
我要强制在这些情况下,某些字段的值。例如,我想将实例user
字段设置为当前登录用户。我不希望用户可以更改此字段的值,因此我不希望它出现在表单中。因此,我使用自定义ModelForm从表单中删除这些字段:
class OrderForm(forms.ModelForm):
class Meta:
model = Order
# For security, we control exactly which fields are placed
# in the form, rather than excluding some:
fields = ('items',)
现在我想新创建的单实例有user
字段设置为当前登录的用户。我无法找到任何关于最佳这种方式的文档。
(A)我可以覆盖形式的save()
方法保存之前修改的对象,但感觉这样的代码并不形式,它不知道关于user
场什么的归属。我也无法访问此处的request
,我需要确定当前用户。但它也可能是这样的:
class OrderForm(forms.ModelForm):
def save(self, commit=True):
instance = super(OrderForm, self).save(commit=False)
instance.user = get_request_magic().user
if commit:
instance.save()
return instance
(B)我可以override the view's form_valid
method保存对象与提交=假像this question基于类的版本。但是我不能直接调用超类的方法,因为它保存的对象没有办法禁用提交,所以我必须手动跳过生成form_valid
这是很讨厌的一代。除此之外投诉,这看起来像到目前为止,我已经找到了最好的方法:
class OrderView(CreateView):
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.save()
return super(ModelFormMixin, self).form_valid(form)
(C)我可以写CreateView
更换,增加了一个钩子,让物体在保存之前改变他们。但是,这感觉就像更多的样板和重复。
(D)我不能provide an initial
value,因为没有表单域来放置它,所以它将被忽略。
还有其他想法吗?如果(B)是最好的选择,是否有任何方法可以手动指定我想调用哪个超类'form_valid
方法?
不幸的是,最后一部分不起作用。在'ModelForm'' save()'方法中,我们现在可以访问'request',但不能访问新的实例!这是由'save_instance'函数(不是方法)创建的,它调用'construct_instance'函数(不是方法),所以我必须重写这两个函数,并且它会再次变得难看。 – qris