クラスベースのビューを使用したフォーム処理—Djangoドキュメント

提供:Dev Guides
< DjangoDjango/docs/3.2.x/topics/class-based-views/generic-editing
移動先:案内検索

クラスベースのビューによるフォーム処理

フォーム処理には通常、次の3つのパスがあります。

  • 初期GET(空白または事前入力されたフォーム)
  • 無効なデータを使用したPOST(通常はエラーのあるフォームを再表示します)
  • 有効なデータを使用したPOST(データを処理し、通常はリダイレクトします)

これを自分で実装すると、多くの場合、ボイラープレートコードが繰り返されます(ビューでのフォームの使用を参照)。 これを回避するために、Djangoはフォーム処理用の汎用クラスベースビューのコレクションを提供します。

基本的なフォーム

お問い合わせフォームを指定します。

forms.py

from django import forms

class ContactForm(forms.Form):
    name = forms.CharField()
    message = forms.CharField(widget=forms.Textarea)

    def send_email(self):
        # send email using the self.cleaned_data dictionary
        pass

ビューは、FormViewを使用して作成できます。

views.py

from myapp.forms import ContactForm
from django.views.generic.edit import FormView

class ContactFormView(FormView):
    template_name = 'contact.html'
    form_class = ContactForm
    success_url = '/thanks/'

    def form_valid(self, form):
        # This method is called when valid form data has been POSTed.
        # It should return an HttpResponse.
        form.send_email()
        return super().form_valid(form)

ノート:


モデルフォーム

モデルを操作するとき、一般的なビューは本当に輝いています。 これらの汎用ビューは、使用するモデルクラスを決定できる限り、 ModelForm を自動的に作成します。

  • model 属性が指定されている場合、そのモデルクラスが使用されます。
  • get_object()がオブジェクトを返す場合、そのオブジェクトのクラスが使用されます。
  • queryset が指定されている場合、そのクエリセットのモデルが使用されます。

モデルフォームビューは、モデルを自動的に保存する form_valid()実装を提供します。 特別な要件がある場合は、これをオーバーライドできます。 例については、以下を参照してください。

CreateView または UpdateViewsuccess_urlを提供する必要はありません。可能な場合は、モデルオブジェクトで get_absolute_url()を使用します。 。

カスタム ModelForm を使用する場合(たとえば、検証を追加する場合)、ビューで form_class を設定します。

ノート

form_classModelForm の場合でも、カスタムフォームクラスを指定する場合は、モデルを指定する必要があります。


まず、 get_absolute_url()Authorクラスに追加する必要があります。

models.py

from django.db import models
from django.urls import reverse

class Author(models.Model):
    name = models.CharField(max_length=200)

    def get_absolute_url(self):
        return reverse('author-detail', kwargs={'pk': self.pk})

次に、 CreateView とその仲間を使用して実際の作業を行うことができます。 ここで、一般的なクラスベースのビューを構成していることに注目してください。 自分でロジックを書く必要はありません。

views.py

from django.urls import reverse_lazy
from django.views.generic.edit import CreateView, DeleteView, UpdateView
from myapp.models import Author

class AuthorCreateView(CreateView):
    model = Author
    fields = ['name']

class AuthorUpdateView(UpdateView):
    model = Author
    fields = ['name']

class AuthorDeleteView(DeleteView):
    model = Author
    success_url = reverse_lazy('author-list')

ノート

ファイルのインポート時にURLがロードされないため、reverse()の代わりに reverse_lazy()を使用する必要があります。


fields属性は、 ModelForm の内部Metaクラスのfields属性と同じように機能します。 別の方法でフォームクラスを定義しない限り、属性は必須であり、そうでない場合、ビューは ImpproperlyConfigured 例外を発生させます。

fields 属性と form_class 属性の両方を指定すると、 ImpproperlyConfigured 例外が発生します。

最後に、これらの新しいビューをURLconfにフックします。

urls.py

from django.urls import path
from myapp.views import AuthorCreateView, AuthorDeleteView, AuthorUpdateView

urlpatterns = [
    # ...
    path('author/add/', AuthorCreateView.as_view(), name='author-add'),
    path('author/<int:pk>/', AuthorUpdateView.as_view(), name='author-update'),
    path('author/<int:pk>/delete/', AuthorDeleteView.as_view(), name='author-delete'),
]

ノート

これらのビューは、 template_name_suffix を使用してモデルに基づいて template_name を構築する SingleObjectTemplateResponseMixin を継承します。

この例では:

CreateViewUpdateView に別々のテンプレートが必要な場合は、ビュークラスに template_name または template_name_suffix のいずれかを設定できます。


モデルとrequest.user

CreateView を使用してオブジェクトを作成したユーザーを追跡するには、カスタム ModelForm を使用してこれを行うことができます。 まず、モデルに外部キー関係を追加します。

models.py

from django.contrib.auth.models import User
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=200)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)

    # ...

ビューで、編集するフィールドのリストにcreated_byが含まれていないことを確認し、 form_valid()をオーバーライドしてユーザーを追加します。

views.py

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views.generic.edit import CreateView
from myapp.models import Author

class AuthorCreateView(LoginRequiredMixin, CreateView):
    model = Author
    fields = ['name']

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

LoginRequiredMixin は、ログインしていないユーザーがフォームにアクセスできないようにします。 これを省略すると、 form_valid()で許可されていないユーザーを処理する必要があります。


コンテントネゴシエーションの例

これは、APIベースのワークフローと「通常の」フォームPOSTで機能するフォームを実装する方法を示す例です。

from django.http import JsonResponse
from django.views.generic.edit import CreateView
from myapp.models import Author

class JsonableResponseMixin:
    """
    Mixin to add JSON support to a form.
    Must be used with an object-based FormView (e.g. CreateView)
    """
    def form_invalid(self, form):
        response = super().form_invalid(form)
        if self.request.accepts('text/html'):
            return response
        else:
            return JsonResponse(form.errors, status=400)

    def form_valid(self, form):
        # We make sure to call the parent's form_valid() method because
        # it might do some processing (in the case of CreateView, it will
        # call form.save() for example).
        response = super().form_valid(form)
        if self.request.accepts('text/html'):
            return response
        else:
            data = {
                'pk': self.object.pk,
            }
            return JsonResponse(data)

class AuthorCreateView(JsonableResponseMixin, CreateView):
    model = Author
    fields = ['name']