【问题标题】:Django mixin and FormView template confusion with CBVDjango mixin 和 FormView 模板与 CBV 混淆
【发布时间】:2019-12-22 02:26:05
【问题描述】:

总的来说,我仍然是 mixins 的菜鸟,所以我只是想了解这段使用 Ajax 提交表单的代码中发生了什么。我一整天都在搜索文档,试图弄清楚发生了什么。该代码似乎有效,但我只是不完全理解为什么。整个过程我还有很多问号所以如果有人能纠正我的想法那就太棒了

  1. AjaxableResponseMixin 扩展了 FormView 的 form_invalid() 和 form_valid() 方法以支持 Ajax 请求

    • 为什么 Ajax 类用 super() 引用自己?
    • 类如何知道扩展 FormView 的方法?
  2. 如果请求不是 Ajax 则返回响应

    • 响应对象有什么作用/有什么?它是否显示模板?它有模板的上下文吗?
  3. CreatePostView是传入的两个父类(AjaxableResponseMixin、FormView)的子类

    • 在调用 super() 时,参数中类的顺序是否会产生影响?
    • 当 CreatePostView 调用 form_valid() 和 form_invalid() 时是否覆盖了 Ajax 类?如果不是,它改变了哪些类方法?
  4. 如果表单有效,则创建帖子并调用 super().form_valid(),然后重定向到成功 url,因为 FormView.form_valid() 就是这样做的

    • 同样,为什么 super() 指的是 FormView?
    • 我最好只做一个 HttpResponseRedirect 而不是使用 super().form_valid()
  5. 如果表单无效,它会重定向到带有“create_post”名称的 url

    • 如何重定向到创建帖子页面并将数据保留在用户尝试提交的表单中?

views.py

class AjaxableResponseMixin(object):
    """
    Mixin to add AJAX support to a form.
    Must be used with an object-based FormView (e.g. CreateView)
    """
    def form_invalid(self, form):
        response = super(AjaxableResponseMixin, self).form_invalid(form)
        if self.request.is_ajax():
            return JsonResponse(form.errors, status=400)
        else:
            return response

    def form_valid(self, form):
        response = super(AjaxableResponseMixin, self).form_valid(form)
        if self.request.is_ajax():
            data = {
                'pk': self.object.pk,
            }
            return JsonResponse(data)
        else:
            return response


class CreatePostView(AjaxableResponseMixin, FormView):
    form_class = CreatePostForm
    template_name = 'forum/create_post.html'
    success_url = reverse_lazy('home')

    def form_valid(self, form):
        user = self.request.user
        form.create_post(user_obj=user)
        messages.success(self.request, 'Your post was published')
        return super().form_valid(form)

    def form_invalid(self, form):
        messages.error(self.request, 'Your post could not be published. Please try again')
        return HttpResponseRedirect(reverse('create_post'))

非常感谢任何回答的人。

【问题讨论】:

  • 这在python中被称为多重继承,基本上你的问题是this的重复

标签: django ajax django-forms mixins django-class-based-views


【解决方案1】:

您的大部分问题都与 python 多重继承和 MRO(方法解析顺序)有关。查一下,还有很多其他资源可以详细解释。但为了帮助您解决具体情况,您已按以下顺序定义继承:

 CreatePostView --> AjaxableResponseMixin ...> FormView

这是调用子类方法的顺序。我使箭头不同,因为第一个是子类-父类关系,第二个不是(CreatePostViewFormViewAjaxableResponseMixin 的子类)

我将解释form_valid 会发生什么:因此,如果您在CreatePostView 上调用form_valid() 方法,则会调用其form_valid() 方法。这会运行该方法的所有代码。

那个方法的最后一行是return super().form_valid(form)告诉python调用父类的方法。对于 MRO,这就是 AjaxableResponseMixin.form_valid 方法。但是第一行是response = super().form_valid(...),也就是FormView.form_valid()

所以在这里,因为super() 位于开头,所以您有效地告诉python 首先转到MRO 链中的下一个。

AjaxableResponseMixin 如果请求是 ajax 请求,则对 super() 响应不做任何事情(它以对象 pk 作为数据返回 JSON),但如果它不是 ajax 请求,它只返回 FormView 响应。在这种情况下,它是对success_url 的重定向,因为这是FormView 在成功的情况下所做的。你可以看到here

现在您可以使用form_invalid() 进行相同的练习。事实上,它应该只是return super().form_invalid(form)。它永远不应该重定向,因为您希望它在同一页面上render 相同的表单(在正常情况下)或者只是在 ajax 情况下报告表单错误。

注意事项:

  • 如果你的方法没有调用super(),这是完全合法的,那么永远不会调用父类的方法。
  • 类的顺序和调用的顺序很重要。使用 Django CBV,您通常会首先调用 super() 来处理基础知识(默认行为),然后添加您自己的东西。在您的form_valid 中,您反其道而行之,因为您首先要保存对象,否则 JSON 不能包含对象的 pk。实际上,如果使用不当,这个 mixin 会在该行崩溃。
  • AjaxableResponseMixin 这样的mixin 不包含任何强制它与FormView“混合”的python 代码,但它必须这样做,因为它调用super().form_valid()。事实上,许多 IDE 都会通过该调用向您发出警告。没有办法告诉 python AjaxableResponseMixin 必须FormView 混合,但它应该是文档的一部分,以便其他开发人员知道如何使用它。对于必须在调用AjaxableResponseMixin.form_valid 之前保存对象的警告也是如此。

【讨论】:

    猜你喜欢
    • 2012-02-25
    • 2011-05-17
    • 2014-07-07
    • 2020-10-07
    • 2011-07-17
    • 1970-01-01
    • 2015-04-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多