Class Based Viewを作成したいとしますupdatesとcreatesオブジェクトを作成します。 前の質問 から、次のいずれかを実行できることがわかりました。
1)2つの汎用ビューCreateView
およびUpdateView
を使用します。これは、2つの異なるクラスを指す2つのURLがあることを意味すると思います。
2)ベースView
を継承するクラスベースのビューを使用します。これは、2つのURLが1つのクラスのみを指すことを意味すると思います(View
を継承するように作成しました)。
2つの質問があります。
a)どちらが良いですか?
b) ccbv.co.uk はベースView
を示していますが、ドキュメントにget、postなどのメソッドが記載されていません。これで正しいですか?
単一のビューで作成と更新の両方を処理する必要があるのはなぜですか?それぞれがそれぞれの汎用ビュークラスから継承する2つの個別のビューを持つ方がはるかに簡単です。必要に応じて、同じフォームとテンプレートを共有でき、それらは異なるURLから提供される可能性が高いため、単一のビューにすると何が得られるかわかりません。
したがって、2つのビューを使用します。1つはCreateView
から継承し、もう1つはUpdateView
から継承します。これらは、必要となる可能性のあるほとんどすべてを処理しますが、2番目のアプローチでは、自分でホイールを再発明する必要があります。オブジェクトの作成時と更新時の両方で使用される一般的な「ハウスキーピング」コードがある場合、ミックスインを使用するオプション、または両方のケースをカバーする独自のビューを作成して、両方から継承する場合はCreateView
およびUpdateView
。
私はこのようなものが欲しかった状況に遭遇しました。これが私が思いついたものです(更新ビューとして使用しようとしていて、要求されたオブジェクトが見つからない場合、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メソッドは_self.object = None
_を設定し、UpdateView
はself.get_object()
に設定します。私がやったことは、これら2つを_CreateUpdateView.get_object
_メソッドで結合するだけです。これは、親クラスの_get_object
_を呼び出そうとして、オブジェクトがない場合に例外を発生させるのではなく、None
を返します。
更新ビューとして使用するときに404ページを提供するには、おそらく_as_view
_をオーバーライドして、それに_update_only
_ブール引数を渡すことができます。 _update_only
_が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および2.1で動作することを確認します。
UpdateView
とCreateView
の間でコードを共有するには、結合されたクラスを作成する代わりに、共通のスーパークラスをミックスインとして使用できます。そうすれば、さまざまな懸念事項を分離する方が簡単な場合があります。そして-多くの既存の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
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 = [...]
Django SmartjanはDjangoのCBVからヒントを得たものです。ドキュメントの例は次のとおりです。 https://smartmin.readthedocs.org/en/latest/quickstart .html
すべての中で最もシンプルで基本的に最良のソリューション 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