使用CreateView将请求变量传递给模型的最佳方法是什么?

时间:2013-01-18 01:17:36

标签: django django-forms

我正在开发一个消息系统,我想根据当前登录的用户设置消息的发起者。

class Message(models.Model):
    originator = models.ForeignKey(User, related_name='+')
    destination = models.ForeignKey(User, related_name='+')
    subject = models.CharField(max_length=100)
    content = models.TextField()

我使用ModelForm和CreateView来表示:

class MessageForm(forms.ModelForm):

    class Meta:
        model = Message
        fields = ('destination', 'subject', 'content')

因此,在保存此表单之前,需要将originator设置为当前登录的用户。我不认为在这里覆盖模型的save方法是合适的,所以我将采用save方法的形式来做,但我不会有权访问请求变量。在another CreateView post中,建议是覆盖get_form_kwargs方法:

class MyFormView(FormView):
    def get_form_kwargs(self):
        # pass "user" keyword argument with the current user to your form
        kwargs = super(MyFormView, self).get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

然而,这不起作用,因为您无法将kwarg user实际传递给ModelForm,因为ModelForm不接受自定义参数。

使用用户信息更新originator变量的最佳(最干净,最实用)方法是什么?

1 个答案:

答案 0 :(得分:3)

在与yuji-tomita-tomita的讨论中,他提出了以下建议,我想分享:

第一种方法依赖于原始代码,使用userget_form_kwargs kwarg发送到表单,然后必须修改与此类似的表单模型:

class MyModelForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):
        self.user = self.kwargs.pop('user', None)
        super(MyModelForm, self).__init__(*args, **kwargs)

这样原始的__init__函数就可以获得它所期望的参数。

但他建议的首选方法是:

class MyView(CreateView):

     def form_valid(self, form):
          obj = form.save(commit=False)
          obj.user = self.request.user
          obj.save()
          return super(MyView, self).form_valid(form)

这非常有效。当form.save(commit=False)方法执行时,它会在表单对象中填充self.instance,并使用与返回变量obj的模型相同的实例。当您通过执行obj更新obj.user = self.request.user并保存它时,form对象具有对此完全相同的对象的引用,因此此处的form对象已经完成。当您将其传递给form_valid的原始CreateView方法时,它会包含所有数据并将成功插入到数据库中。

如果有人有不同的做法,我很乐意听到它!