Представление на основе класса Django для создания и обновления

скажем, я хочу создать Представление На Основе Класса что как обновления и создает объект. Из предыдущий вопрос я понял, что могу сделать одну из следующих вещей:

1) Используйте 2 общих вида CreateView и UpdateView что, я думаю, означало бы наличие двух URL-адресов, указывающих на два разных класса.

2) Используйте представление на основе класса, которое наследует base View, что, я думаю, будет означать наличие двух URL-адресов указывая только на 1 класс (я создал, который наследует View).

у меня два вопроса:

a) что лучше?

b) ccbv.co.Великобритания показывает базу View, но я не вижу никаких методов get, post и т. д., Это правильно?

5 ответов


Почему вам нужно обрабатывать как создание, так и обновление одним представлением? Гораздо проще иметь два отдельных представления, каждое из которых наследуется от соответствующего универсального класса представления. Они могут использовать одну и ту же форму и шаблон, если вы хотите, и они, скорее всего, обслуживаются из разных URL-адресов, поэтому я не вижу, что вы получите, сделав это в одном представлении.

Итак: используйте два представления, один из которых наследуется от CreateView а другой из UpdateView. Они управляют почти всем, что вам может понадобиться, в то время как второй подход потребуется изобретать велосипед самому. Если у вас есть какой-то общий "домашний" код, который используется как при создании, так и при обновлении объектов, опция использования mixin или вы можете создать свое собственное представление, которое охватывает оба варианта использования, наследуя от обоих CreateView и UpdateView.


я столкнулся с ситуацией, когда я хотел что-то подобное. Вот что я придумал (обратите внимание, что если вы пытаетесь использовать его как представление обновления, и он не может найти запрошенный объект, он будет вести себя как представление create, а не бросать 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)

получается, что UpdateView и CreateView наследовать от точно таких же классов и миксины. Единственное различие заключается в методах 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 методы set self.object = None С UpdateView С self.get_object(). Все, что я сделал, это объединил эти два в моем CreateUpdateView.get_object метод, который пытается вызвать родительский класс' get_object и возвращает None вместо того, чтобы вызывать исключение, если нет объекта.

чтобы обслуживать страницу 404 при использовании в качестве представления обновления, вы, вероятно, можете переопределить as_view и передать ему update_only логический аргумент. Если update_only is True и представление не может найти объект, а затем поднять 404.


Как предложил @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.7.


поделиться код между UpdateView и CreateView, вместо создания объединенного класса, вы можете использовать общий суперкласс в качестве 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

вы также можете использовать Django Smartmin, который вдохновлен CBV Django. Вот пример из документации:https://smartmin.readthedocs.org/en/latest/quickstart.html