Представление на основе класса 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