在Django中的类视图CreateView中访问request.user以设置外键字段

36

所以我有一个包括以下内容的模型:

class Place(models.Model):
    ....
    created_by = models.ForeignKey(User)

我的视图像这样:

class PlaceFormView(CreateView):
    form_class = PlaceForm

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(PlaceFormView, self).dispatch(*args, **kwargs)
有没有办法让我访问request.user并将created_by设置为该用户?我查看了文档,但似乎找不到任何提示。
3个回答

35

你可以尝试覆盖form_valid方法来保存表单。在保存表单后,你可以对其进行任意修改,然后再进行重定向操作。

class PlaceFormView(CreateView):
    form_class = PlaceForm

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(PlaceFormView, self).dispatch(*args, **kwargs)

    def form_valid(self, form):
        obj = form.save(commit=False)
        obj.created_by = self.request.user
        obj.save()        
        return http.HttpResponseRedirect(self.get_success_url())

1
谢谢!这个代码可以运行,除了重定向。我收到了错误信息:“没有要重定向的URL。请提供一个URL或在模型上定义get_absolute_url方法。”然而,我的模型上已经设置了get_absolute_url()方法,并且当我第一次使用这个视图(带有表单上的created_by选择框)时,它可以正确地重定向。现在正在尝试解决这个问题。你有什么想法吗? - Brian
1
是的,似乎get_absolute_url是从self.object中提取的 - 所以在您的代码中,在form_valid中设置self.object = obj - Yuji 'Tomita' Tomita
能否在不扩展CreateView的情况下完成这个操作? - john2x
1
我们不应该在form_valid的末尾执行以下操作吗: return super(PlaceFormView, self).form_valid(form) 否则默认的form_valid将永远不会被调用... - Marc
@Marc,“default” form_valid 做相同的事情,你可以在 ccbv.co.uk 上轻松地检查它,它只是保存对象并重定向。 - José Tomás Tocino
太棒了!像魔法一样好用! - marlonjd

23

我知道这篇文章比较老,但是对于其他有这个问题的人:

有一种更简单的方法 - 因为保存表单多次会始终使用同一个模型实例,所以你也可以这样做:

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

这样做,您可以获得超级调用的所有好处 - 很容易看出您实际上只需添加这两行代码,而不必通过复制重定向逻辑来重复自己。


5

另一种做法是通过在CreateView中覆盖get_initial()方法将用户传递,并修改PlaceForm类的save方法以保存用户:

class PlaceForm(forms.ModelForm):
    ...
    ...
    ...

    def __init__(self, *args, **kwargs):
        self.created_by = kwargs['initial']['created_by']
        super(PlaceForm, self).__init__(*args, **kwargs)

    def save(self, commit=True):
        obj = super(PlaceForm, self).save(False)
        obj.created_by = self.created_by
        commit and obj.save()
        return obj

class PlaceFormView(CreateView):
    ...
    ...
    form_class = PlaceForm

    def get_initial(self):
        self.initial.update({ 'created_by': self.request.user })
        return self.initial

通过这种方式,节省逻辑仍然封装在表单类中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接