【问题标题】:Accessing request.user in class based generic view CreateView in order to set FK field in Django在基于类的通用视图 CreateView 中访问 request.user 以便在 Django 中设置 FK 字段
【发布时间】:2011-08-12 17:53: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 设置为该用户?我浏览了文档,但似乎找不到任何提示。

`

【问题讨论】:

    标签: django django-generic-views django-class-based-views


    【解决方案1】:

    如何覆盖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())
    

    【讨论】:

    • 谢谢!这有效,除了重定向。我收到错误消息:“没有要重定向到的 URL。请提供 url 或在模型上定义 get_absolute_url 方法。”但是,我确实在模型上设置了 get_absolute_url() ,并且当我第一次使该视图正常工作时(使用 created_by 表单上的选择框),它正确重定向。现在试图弄清楚这一点。有什么想法吗?
    • 是的,似乎 get_absolute_url 是从 self.object 中提取的 - 所以在您的代码中,将 self.object = obj 设置为 form_valid
    • 是否可以在不扩展 CreateView 的情况下做到这一点?
    • 我们不应该在form_valid的末尾做:return super(PlaceFormView, self).form_valid(form) 否则永远不会调用默认的form_valid...
    • @Marc "default" form_valid 也是如此,您可以在 ccbv.co.uk 轻松查看,它只是保存对象并重定向。
    【解决方案2】:

    我知道这是旧的,但对于其他有这个问题的人:

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

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

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

    【讨论】:

      【解决方案3】:

      另一种方法是通过覆盖 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
      

      这样保存逻辑仍然封装在表单类中。

      【讨论】:

        猜你喜欢
        • 2021-06-28
        • 2014-10-12
        • 2011-06-28
        • 2016-12-25
        • 2014-08-19
        • 1970-01-01
        • 2018-03-04
        • 2014-01-22
        • 2011-10-31
        相关资源
        最近更新 更多