Django基于类的创建和更新视图

fcg9iug3  于 2023-06-25  发布在  Go
关注(0)|答案(8)|浏览(159)

假设我想创建一个Class Based View,它既更新,又创建一个对象。从一个previous question我计算出我可以做以下事情之一:
1)使用两个通用视图CreateViewUpdateView,我认为这意味着有两个URL指向两个不同的类。
2)使用一个继承了View的基于类的视图,我认为这意味着有两个URL指向一个类(我创建了继承了View的类)。
我有两个问题:

a)哪个更好?

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

vxf3dgd4

vxf3dgd41#

我遇到了一个情况,我想要这样的东西。下面是我的想法(请注意,如果你试图将其用作更新视图,而它无法找到所请求的对象,它将表现为创建视图,而不是抛出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继承自完全相同的类和mixin。唯一的区别是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 = None,而UpdateView将其设置为self.get_object()。我所做的就是在我的CreateUpdateView.get_object方法中将这两个结合起来,该方法试图调用父类'get_object并返回None,而不是在没有对象的情况下引发异常。
要将404页面用作更新视图,您可能需要覆盖as_view并向其传递update_only布尔参数。如果update_onlyTrue,并且视图找不到对象,则引发404。

qgzx9mmu

qgzx9mmu2#

就像@scubabuddha建议的那样,我遇到了类似的情况,我使用了他的回答,修改为@mario-orlandi在评论中建议的:

from django.views.generic import UpdateView

class CreateUpdateView(UpdateView):

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

我在Django 1.11中使用了这个解决方案,但我认为它可以在Django 2.0中工作。

更新

我确认此解决方案适用于Django 2.0/2.1/2.2

zvokhttg

zvokhttg3#

最简单,基本上是所有link中最好的解决方案

class WorkerUpdate(UpdateView):
    form_class = WorkerForm

    def get_object(self, queryset=None):

        # get the existing object or created a new one
        obj, created = Worker.objects.get_or_create(mac=self.kwargs['mac'])

        return obj

谢谢@chriskief

snz8szmq

snz8szmq4#

如果你不需要引发404,并且希望所有字段都为空,如果对象不存在,在第一次保存和更新时创建对象,当它存在时,你可以使用这个。
views.py

from django.views.generic import UpdateView

class CreateUpdateView(UpdateView):
    model = MyModel
    form_class = MyModelForm

    def get_object(self, queryset=None):
        return self.model.objects.filter(...).first()

forms.py

class MyModelForm(forms.ModelForm):

    class Meta:
        model = MyModel
        fields = [...]
neekobn8

neekobn85#

为什么需要通过一个视图来处理创建和更新?拥有两个单独的视图要简单得多,每个视图都继承自其各自的泛型视图类。如果您愿意,它们可以共享相同的表单和模板,而且它们很可能来自不同的URL,所以我不知道将其制作成单个视图会得到什么。
所以:使用两个视图,一个继承自CreateView,另一个继承自UpdateView。这些方法几乎可以处理您可能需要的所有内容,而第二种方法则需要您自己重新发明轮子。如果在创建或更新对象时使用一些常见的“内务”代码,可以选择使用mixin,或者您可以创建自己的视图,涵盖这两种用例,继承CreateViewUpdateView

vatpfxk5

vatpfxk56#

你也可以使用Django Smartmin,它的灵感来自Django的CBV。下面是文档中的一个示例:https://smartmin.readthedocs.org/en/latest/quickstart.html

xxls0lw8

xxls0lw87#

要在UpdateViewCreateView之间共享代码,您可以使用一个公共超类作为mixin,而不是创建一个组合类。这样,可能更容易分离不同的关注点。而且-你可以重用大量现有的Django代码。

class BookFormView(PJAXContextMixin):
    template_name = 'library/book_form.html'
    form_class = BookForm

    def form_valid(self, form):
        form.instance.owner = self.request.user
        return super().form_valid(form)

    class Meta:
        abstract = True

class BookCreateView(BookFormView, CreateView):
    pass

class FormatUpdateView(BookFormView, UpdateView):
    queryset = Book.objects
evrscar2

evrscar28#

在我的例子中,它是如何适应UpdateView与Singleton提供的答案。这就是为什么我把硬编码pk=1。简化类:

class MyClass(UpdateView):
    ...
    def get_object(self):
        obj, _ = MyClass.objects.update_or_create(pk=1)
        return obj

https://docs.djangoproject.com/en/4.2/ref/models/querysets/#update-or-create

相关问题