用于创建和更新的基于 Django 类的 View

标签 django django-models django-views django-class-based-views

假设我想创建一个基于类的 View ,它既更新创建一个对象。来自 previous question我发现我可以做以下事情之一:

1) 使用 2 个通用 View CreateViewUpdateView,我认为这意味着有两个 URL 指向两个不同的类。

2) 使用继承基础 View 的基于类的 View ,我认为这意味着有两个 URL 指向仅 1 个类(我创建的继承 View)。

我有两个问题:

a) 哪个更好?

b) ccbv.co.uk显示了一个基本的 View,但我没有看到任何 get、post 等方法的文档,这是正确的吗?

最佳答案

我遇到了我想要这样的东西的情况。这是我想出的(请注意,如果您尝试将其用作更新 View 并且找不到请求的对象,它将表现为创建 View 而不是抛出 404):

from django.views.generic.detail import SingleObjectTemplateResponseMixin
from django.views.generic.edit import ModelFormMixin, ProcessFormView

class CreateUpdateView(
    SingleObjectTemplateResponseMixin, ModelFormMixin, ProcessFormView
):

    def get_object(self, queryset=None):
        try:
            return super(CreateUpdateView,self).get_object(queryset)
        except AttributeError:
            return None

    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super(CreateUpdateView, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super(CreateUpdateView, self).post(request, *args, **kwargs)

事实证明,UpdateViewCreateView 继承自完全相同的类和混入。唯一的区别在于 get/post 方法。以下是它们在 Django 源代码 (1.8.2) 中的定义方式:

class BaseCreateView(ModelFormMixin, ProcessFormView):
    """
    Base view for creating an new object instance.

    Using this base class requires subclassing to provide a response mixin.
    """
    def get(self, request, *args, **kwargs):
        self.object = None
        return super(BaseCreateView, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = None
        return super(BaseCreateView, self).post(request, *args, **kwargs)


class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView):
    """
    View for creating a new object instance,
    with a response rendered by template.
    """
    template_name_suffix = '_form'


class BaseUpdateView(ModelFormMixin, ProcessFormView):
    """
    Base view for updating an existing object.

    Using this base class requires subclassing to provide a response mixin.
    """
    def get(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super(BaseUpdateView, self).get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = self.get_object()
        return super(BaseUpdateView, self).post(request, *args, **kwargs)


class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView):
    """
    View for updating an object,
    with a response rendered by template.
    """
    template_name_suffix = '_form'

如您所见,CreateView get 和 post 方法设置了 self.object = NoneUpdateView 将其设置为 self.get_object()。我所做的就是在我的 CreateUpdateView.get_object 方法中结合这两者,该方法尝试调用父类的 get_object 并返回 None 而不是如果没有对象则引发异常。

要在用作更新 View 时提供 404 页面,您可能可以覆盖 as_view 并向其传递一个 update_only bool 参数。如果 update_onlyTrue 并且 View 找不到该对象,则引发 404。

关于用于创建和更新的基于 Django 类的 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17192737/

相关文章:

django - 如何获取 django 应用程序中所有 View 的列表?

python - 方法对象不是 JSON 可序列化的

python - Django : Timeout when reading response headers from daemon process 的 mod_wsgi 错误

python - 如何重定向到 Django 中的动态 URL

python - 通用详细 View UserProfileDetailView 必须使用对象 pk 或 URLconf 中的 slug 调用

python - “元组”对象没有属性 'all'

django - 如何获取 AutoField 的计数器值?

django - 在 Django 中分组和排序

django - 使用 Django 为每个应用程序设置不同的设置

javascript - Django - 复制管理 list_display