【问题标题】:django class-based view - UpdateView - How to access the request user while processing a form?django 基于类的视图 - UpdateView - 如何在处理表单时访问请求用户?
【发布时间】:2012-03-02 23:49:41
【问题描述】:

在 Django 的基于类的 UpdateView 中,我排除了用户字段,因为它是系统内部的,我不会要求它。现在将用户传递给表单的正确 Django 方式是什么。 (我现在怎么做,是我将用户传递到表单的 init 中,然后覆盖表单的 save() 方法。但我敢打赌,有一种正确的方法可以做到这一点。像一个隐藏的领域或那种性质的东西。

# models.py
class Entry(models.Model):
    user = models.ForeignKey(
                User,
                related_name="%(class)s",
                null=False
    )

    name = models.CharField(
                blank=False, 
                max_length=58,
    )

    is_active = models.BooleanField(default=False)

    class Meta:
        ordering = ['name',]

    def __unicode__(self):
        return u'%s' % self.name

# forms.py
class EntryForm(forms.ModelForm):
    class Meta:
        model = Entry
        exclude = ('user',)

# views.py
class UpdateEntry(UpdateView):
    model = Entry
    form_class = EntryForm
    template_name = "entry/entry_update.html"
    success_url = reverse_lazy('entry_update')

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

# urls.py
url(r'^entry/edit/(?P<pk>\d+)/$',
    UpdateEntry.as_view(),
    name='entry_update'
),

【问题讨论】:

    标签: django django-class-based-views


    【解决方案1】:

    像传递隐藏字段一样进行黑客攻击是没有意义的,因为这确实与客户端无关 - 这个经典的“与登录用户关联”问题绝对应该在服务器端处理。

    我会将此行为放在form_valid 方法中。

    class MyUpdateView(UpdateView):
        def form_valid(self, form):
            instance = form.save(commit=False)
            instance.user = self.request.user
            super(MyUpdateView, self).save(form)
    
       # the default implementation of form_valid is...
       # def form_valid(self, form):
       #     self.object = form.save()
       #     return HttpResponseRedirect(self.get_success_url())
    

    【讨论】:

    • 我建议删除最后两行(.save()return)并用super(MyUpdateView, self).form_valid(form) 替换它们。这将在您修改的表单实例上简单地执行默认的 form_valid() (与您的最后两行相同),使您的代码与 Django 项目对 this 方法所做的任何未来更改保持同步。
    • @Bryson,很好!我以前从来没有这样做过。我想在 form.instance 上引用实例并不是很直观,因此修改会再次影响未来的 save() 调用。
    • 我错过了一些东西:而不是只使用instance =,我相信你应该使用form.instance =。这会将请求对象中的用户(假设您的表单是使用此字段制作的,否则会出现“表单没有属性'user'”之类的错误)添加到表单实例,然后将通过@ 987654330@。正如现在写的那样,带有用户数据的修改后的表单保存在一个名为instance 的变量中,它永远不会离开您的form_valid 版本,所以因为您切换到super(),它永远不会被保存。抱歉,事情变得复杂了。哈哈
    • 补充一点,如果您使用commit=false,并且您的模型也有多对多字段,则需要显式调用form.save_m2m() 来保存多对多对象。
    • 这个案例现在被“基于类的视图”主题中的Django docs 覆盖。请注意,除了装饰器,您还可以使用来自django.contrib.auth.mixinsLoginRequiredMixin
    【解决方案2】:

    必须返回一个 HttpResponse 对象。下面的代码有效:

    class MyUpdateView(UpdateView):
        def form_valid(self, form):
            instance = form.save(commit=False)
            instance.user = self.request.user
            return super(MyUpdateView, self).form_valid(form)
    

    【讨论】:

      【解决方案3】:

      我们也可以这样做

      class MyUpdateView(UpdateView):
          form_class = SomeModelForm
      
          def form_valid(self, form):
              form.instance.user = self.request.user
              return super(MyUpdateView, self).form_valid(form)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-02-07
        • 1970-01-01
        • 2016-12-05
        • 2016-02-21
        • 2022-07-02
        • 2017-11-07
        • 2022-01-10
        相关资源
        最近更新 更多