我有一个 Django 应用程序,用户可以在其中提交付款订单。显然,安全很重要。我想尽量减少我必须编写的代码量,以避免引入任何安全漏洞,并简化维护。
模型很简单:
class Order(models.Model):
user = models.ForeignKey(User)
created = models.DateTimeField()
paid = models.DateTimeField(null=True, blank=True)
items = models.ManyToManyField(Item)
我正在使用CreateView创建 Order 实例:
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',)
现在我希望新创建的 Order 实例将该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)我可以用 commit=False覆盖视图的form_valid
方法来保存对象,就像这个 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)我不能提供initial
值,因为没有表单域可以放入,所以会被忽略。
还有其他想法吗?如果(B)是最好的选择,有什么办法可以绕过手动指定form_valid
我想调用哪个超类的方法吗?