---
title: "クラスベースのビューでミックスインを使用する"
version: 3.1
locale: ja
source: https://docs.djangoproject.com/ja/3.1/topics/class-based-views/mixins/
canonical: https://djangodocs.dev/ja/3.1/topics/class-based-views/mixins/
---
# クラスベースのビューでミックスインを使用する

> **Caution**
>
> これは発展的なトピックです。これらのテクニックについて詳しく読む前に、[Django's class-based views](/ja/3.1/topics/class-based-views/) で動作のしくみを知っておくことをおすすめします。

Django のビルトインのクラスベースビューではたくさんの機能が準備されていますが、個別に使いたい機能もあるかもしれません。例えば、HTTP レスポンスを生成するテンプレートをレンダリングするビューを記述したいとき、[`TemplateView`](/ja/3.1/ref/class-based-views/base/#django.views.generic.base.TemplateView) は使えない状況もあります; `POST` ではテンプレートをレンダリングするだけで、`GET` のときはまったく異なる処理がしたいときなどです。この場合、[`TemplateResponse`](/ja/3.1/ref/template-response/#django.template.response.TemplateResponse) を直接使えますが、コードが重複する結果となってしまいます。

この理由から、Django は個別の機能を提供する多くの mixin を用意しています。例えば、テンプレートのレンダリングは [`TemplateResponseMixin`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin) でカプセル化されています。Django のリファレンスドキュメントは  [full documentation of all the mixins](/ja/3.1/ref/class-based-views/mixins/) を含んでいます。

## コンテキストとテンプレートのレスポンス

2 つの中心的な mixin が用意されており、クラスベースビュー内のテンプレートを扱うインターフェースに一貫性を保ちやすくなっています。

**[`TemplateResponseMixin`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin)**

  [`TemplateResponse`](/ja/3.1/ref/template-response/#django.template.response.TemplateResponse) を返すビルトインビューは全て、 `TemplateResponseMixin` が提供する [`render_to_response()`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.render_to_response) メソッドを呼び出します。ほとんどの場合、これはあなたによって呼び出されます(たとえば、 [`TemplateView`](/ja/3.1/ref/class-based-views/base/#django.views.generic.base.TemplateView) と [`DetailView`](/ja/3.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView))の両方で実装されている `get()` メソッドによって)。同様に、これをオーバーライドする必要はほとんどありませんが、Django テンプレートでレンダリングされていないものを返したい場合は、オーバーライドする必要があるでしょう。この例については、 [JSONResponseMixin example](#jsonresponsemixin-example) の例を参照してください。

  `render_to_response()` itself calls
  [`get_template_names()`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.get_template_names),
  which by default will look up
  [`template_name`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.template_name) on
  the class-based view; two other mixins
  ([`SingleObjectTemplateResponseMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin)
  and
  [`MultipleObjectTemplateResponseMixin`](/ja/3.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectTemplateResponseMixin))
  override this to provide more flexible defaults when dealing with actual
  objects.

**[`ContextMixin`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin)**

  Every built in view which needs context data, such as for rendering a
  template (including `TemplateResponseMixin` above), should call
  [`get_context_data()`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.get_context_data) passing
  any data they want to ensure is in there as keyword arguments.
  `get_context_data()` returns a dictionary; in `ContextMixin` it
  returns its keyword arguments, but it is common to override this to add
  more members to the dictionary. You can also use the
  [`extra_context`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.extra_context) attribute.

## Django の一般的なクラスベースのビューを構築する

Let's look at how two of Django's generic class-based views are built
out of mixins providing discrete functionality. We'll consider
[`DetailView`](/ja/3.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView), which renders a
"detail" view of an object, and
[`ListView`](/ja/3.1/ref/class-based-views/generic-display/#django.views.generic.list.ListView), which will render a list
of objects, typically from a queryset, and optionally paginate
them. This will introduce us to four mixins which between them provide
useful functionality when working with either a single Django object,
or multiple objects.

There are also mixins involved in the generic edit views
([`FormView`](/ja/3.1/ref/class-based-views/generic-editing/#django.views.generic.edit.FormView), and the model-specific
views [`CreateView`](/ja/3.1/ref/class-based-views/generic-editing/#django.views.generic.edit.CreateView),
[`UpdateView`](/ja/3.1/ref/class-based-views/generic-editing/#django.views.generic.edit.UpdateView) and
[`DeleteView`](/ja/3.1/ref/class-based-views/generic-editing/#django.views.generic.edit.DeleteView)), and in the
date-based generic views. These are
covered in the [mixin reference
documentation](/ja/3.1/ref/class-based-views/mixins/).

### `DetailView`: Django の1つのオブジェクトを対象とするビュー

オブジェクトの詳細を表示するためには、基本的に2つの作業が必要です。まずはオブジェクトを検索し、それから適切なテンプレートと、そのオブジェクトをコンテキストとして、 [`TemplateResponse`](/ja/3.1/ref/template-response/#django.template.response.TemplateResponse) を作成します。

オブジェクトを取得するために、 [`DetailView`](/ja/3.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView) は [`SingleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin) に依存しています。このクラスではリクエストURLに基づいてオブジェクトを見つけ出すメソッド [`get_object()`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_object) を提供しています(このメソッドでは URLConfで宣言されている `pk` および `slug` キーワード引数を検索し、ビューの [`model`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.model) 属性、あるいは提供されている場合は [`queryset`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.queryset) 属性からオブジェクトを検索します)。 `SingleObjectMixin` はまた [`get_context_data()`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.get_context_data) メソッドも提供しています。このメソッドでは、テンプレートレンダーに渡すコンテキストデータを提供するために、Django組み込みのクラスベースビュー全てで使われています。

To then make a [`TemplateResponse`](/ja/3.1/ref/template-response/#django.template.response.TemplateResponse),
[`DetailView`](/ja/3.1/ref/class-based-views/flattened-index/#DetailView) uses
[`SingleObjectTemplateResponseMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin),
which extends [`TemplateResponseMixin`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin),
overriding
[`get_template_names()`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.get_template_names)
as discussed above. It actually provides a fairly sophisticated set of options,
but the main one that most people are going to use is
`<app_label>/<model_name>_detail.html`. The `_detail` part can be changed
by setting
[`template_name_suffix`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin.template_name_suffix)
on a subclass to something else. (For instance, the [generic edit
views](/ja/3.1/topics/class-based-views/generic-editing/) use `_form` for create and update views, and
`_confirm_delete` for delete views.)

### `ListView`: Django の複数のオブジェクトを対象とするビュー

Lists of objects follow roughly the same pattern: we need a (possibly
paginated) list of objects, typically a
[`QuerySet`](/ja/3.1/ref/models/querysets/#django.db.models.query.QuerySet), and then we need to make a
[`TemplateResponse`](/ja/3.1/ref/template-response/#django.template.response.TemplateResponse) with a suitable template
using that list of objects.

To get the objects, [`ListView`](/ja/3.1/ref/class-based-views/generic-display/#django.views.generic.list.ListView) uses
[`MultipleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin), which
provides both
[`get_queryset()`](/ja/3.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.get_queryset)
and
[`paginate_queryset()`](/ja/3.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.paginate_queryset). Unlike
with [`SingleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin), there's no need
to key off parts of the URL to figure out the queryset to work with, so the
default uses the
[`queryset`](/ja/3.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.queryset) or
[`model`](/ja/3.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.model) attribute
on the view class. A common reason to override
[`get_queryset()`](/ja/3.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin.get_queryset)
here would be to dynamically vary the objects, such as depending on
the current user or to exclude posts in the future for a blog.

[`MultipleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin) also overrides
[`get_context_data()`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.ContextMixin.get_context_data) to
include appropriate context variables for pagination (providing
dummies if pagination is disabled). It relies on `object_list` being
passed in as a keyword argument, which [`ListView`](/ja/3.1/ref/class-based-views/flattened-index/#ListView) arranges for
it.

To make a [`TemplateResponse`](/ja/3.1/ref/template-response/#django.template.response.TemplateResponse),
[`ListView`](/ja/3.1/ref/class-based-views/flattened-index/#ListView) then uses
[`MultipleObjectTemplateResponseMixin`](/ja/3.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectTemplateResponseMixin);
as with [`SingleObjectTemplateResponseMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectTemplateResponseMixin)
above, this overrides `get_template_names()` to provide [`a range of
options`](/ja/3.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectTemplateResponseMixin),
with the most commonly-used being
`<app_label>/<model_name>_list.html`, with the `_list` part again
being taken from the
[`template_name_suffix`](/ja/3.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectTemplateResponseMixin.template_name_suffix)
attribute. (The date based generic views use suffixes such as `_archive`,
`_archive_year` and so on to use different templates for the various
specialized date-based list views.)

## Django のクラスベースのビューのミックスインを使用する

Now we've seen how Django's generic class-based views use the provided mixins,
let's look at other ways we can combine them. We're still going to be combining
them with either built-in class-based views, or other generic class-based
views, but there are a range of rarer problems you can solve than are provided
for by Django out of the box.

> **Warning**
>
> Not all mixins can be used together, and not all generic class
> based views can be used with all other mixins. Here we present a
> few examples that do work; if you want to bring together other
> functionality then you'll have to consider interactions between
> attributes and methods that overlap between the different classes
> you're using, and how [method resolution order](https://www.python.org/download/releases/2.3/mro/) will affect which
> versions of the methods will be called in what order.
>
> The reference documentation for Django's [class-based
> views](/ja/3.1/ref/class-based-views/) and [class-based view
> mixins](/ja/3.1/ref/class-based-views/mixins/) will help you in
> understanding which attributes and methods are likely to cause
> conflict between different classes and mixins.
>
> If in doubt, it's often better to back off and base your work on
> [`View`](/ja/3.1/ref/class-based-views/flattened-index/#View) or [`TemplateView`](/ja/3.1/ref/class-based-views/flattened-index/#TemplateView), perhaps with
> [`SingleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin) and
> [`MultipleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin). Although you
> will probably end up writing more code, it is more likely to be clearly
> understandable to someone else coming to it later, and with fewer
> interactions to worry about you will save yourself some thinking. (Of
> course, you can always dip into Django's implementation of the generic
> class-based views for inspiration on how to tackle problems.)

### ビューで `SingleObjectMixin` を使用する

If we want to write a class-based view that responds only to `POST`, we'll
subclass [`View`](/ja/3.1/ref/class-based-views/base/#django.views.generic.base.View) and write a `post()` method
in the subclass. However if we want our processing to work on a particular
object, identified from the URL, we'll want the functionality provided by
[`SingleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin).

We'll demonstrate this with the `Author` model we used in the
[generic class-based views introduction](/ja/3.1/topics/class-based-views/generic-display/).

*views.py*

```python
from django.http import HttpResponseForbidden, HttpResponseRedirect
from django.urls import reverse
from django.views import View
from django.views.generic.detail import SingleObjectMixin
from books.models import Author

class RecordInterest(SingleObjectMixin, View):
    """Records the current user's interest in an author."""
    model = Author

    def post(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return HttpResponseForbidden()

        # Look up the author we're interested in.
        self.object = self.get_object()
        # Actually record interest somehow here!

        return HttpResponseRedirect(reverse('author-detail', kwargs={'pk': self.object.pk}))
```

In practice you'd probably want to record the interest in a key-value
store rather than in a relational database, so we've left that bit
out. The only bit of the view that needs to worry about using
[`SingleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin) is where we want to
look up the author we're interested in, which it does with a call to
`self.get_object()`. Everything else is taken care of for us by the mixin.

We can hook this into our URLs easily enough:

*urls.py*

```python
from django.urls import path
from books.views import RecordInterest

urlpatterns = [
    #...
    path('author/<int:pk>/interest/', RecordInterest.as_view(), name='author-interest'),
]
```

Note the `pk` named group, which
[`get_object()`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_object) uses
to look up the `Author` instance. You could also use a slug, or
any of the other features of
[`SingleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin).

### `ListView` で `SingleObjectMixin` を使用する

[`ListView`](/ja/3.1/ref/class-based-views/generic-display/#django.views.generic.list.ListView) provides built-in
pagination, but you might want to paginate a list of objects that are
all linked (by a foreign key) to another object. In our publishing
example, you might want to paginate through all the books by a
particular publisher.

One way to do this is to combine [`ListView`](/ja/3.1/ref/class-based-views/flattened-index/#ListView) with
[`SingleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin), so that the queryset
for the paginated list of books can hang off the publisher found as the single
object. In order to do this, we need to have two different querysets:

**`` ListView` `` で使用するための `Book` の queryset**

  Since we have access to the `Publisher` whose books we want to list, we
  override `get_queryset()` and use the `Publisher`’s [reverse
  foreign key manager](/ja/3.1/topics/db/queries/#backwards-related-objects).

**`Publisher` queryset for use in [`get_object()`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin.get_object)**

  We'll rely on the default implementation of `get_object()` to fetch the
  correct `Publisher` object.
  However, we need to explicitly pass a `queryset` argument because
  otherwise the default implementation of `get_object()` would call
  `get_queryset()` which we have overridden to return `Book` objects
  instead of `Publisher` ones.

> **Note**
>
> We have to think carefully about `get_context_data()`.
> Since both [`SingleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin) and
> [`ListView`](/ja/3.1/ref/class-based-views/flattened-index/#ListView) will
> put things in the context data under the value of
> `context_object_name` if it's set, we'll instead explicitly
> ensure the `Publisher` is in the context data. [`ListView`](/ja/3.1/ref/class-based-views/flattened-index/#ListView)
> will add in the suitable `page_obj` and `paginator` for us
> providing we remember to call `super()`.

Now we can write a new `PublisherDetail`:

```
from django.views.generic import ListView
from django.views.generic.detail import SingleObjectMixin
from books.models import Publisher

class PublisherDetail(SingleObjectMixin, ListView):
    paginate_by = 2
    template_name = "books/publisher_detail.html"

    def get(self, request, *args, **kwargs):
        self.object = self.get_object(queryset=Publisher.objects.all())
        return super().get(request, *args, **kwargs)

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['publisher'] = self.object
        return context

    def get_queryset(self):
        return self.object.book_set.all()
```

Notice how we set `self.object` within `get()` so we
can use it again later in `get_context_data()` and `get_queryset()`.
If you don't set `template_name`, the template will default to the normal
[`ListView`](/ja/3.1/ref/class-based-views/flattened-index/#ListView) choice, which in this case would be
`"books/book_list.html"` because it's a list of books;
[`ListView`](/ja/3.1/ref/class-based-views/flattened-index/#ListView) knows nothing about
[`SingleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin), so it doesn't have
any clue this view is anything to do with a `Publisher`.

The `paginate_by` is deliberately small in the example so you don't
have to create lots of books to see the pagination working! Here's the
template you'd want to use:

```html+django
{% extends "base.html" %}

{% block content %}
    <h2>Publisher {{ publisher.name }}</h2>

    <ol>
      {% for book in page_obj %}
        <li>{{ book.title }}</li>
      {% endfor %}
    </ol>

    <div class="pagination">
        <span class="step-links">
            {% if page_obj.has_previous %}
                <a href="?page={{ page_obj.previous_page_number }}">previous</a>
            {% endif %}

            <span class="current">
                Page {{ page_obj.number }} of {{ paginator.num_pages }}.
            </span>

            {% if page_obj.has_next %}
                <a href="?page={{ page_obj.next_page_number }}">next</a>
            {% endif %}
        </span>
    </div>
{% endblock %}
```

## Avoid anything more complex

Generally you can use
[`TemplateResponseMixin`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin) and
[`SingleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin) when you need
their functionality. As shown above, with a bit of care you can even
combine `SingleObjectMixin` with
[`ListView`](/ja/3.1/ref/class-based-views/generic-display/#django.views.generic.list.ListView). However things get
increasingly complex as you try to do so, and a good rule of thumb is:

> **Hint**
>
> Each of your views should use only mixins or views from one of the
> groups of generic class-based views: [detail,
> list](/ja/3.1/topics/class-based-views/generic-display/), [editing](/ja/3.1/topics/class-based-views/generic-editing/) and
> date. For example it's fine to combine
> [`TemplateView`](/ja/3.1/ref/class-based-views/flattened-index/#TemplateView) (built in view) with
> [`MultipleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-multiple-object/#django.views.generic.list.MultipleObjectMixin) (generic list), but
> you're likely to have problems combining `SingleObjectMixin` (generic
> detail) with `MultipleObjectMixin` (generic list).

To show what happens when you try to get more sophisticated, we show
an example that sacrifices readability and maintainability when there
is a simpler solution. First, let's look at a naive attempt to combine
[`DetailView`](/ja/3.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView) with
[`FormMixin`](/ja/3.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin) to enable us to
`POST` a Django [`Form`](/ja/3.1/ref/forms/api/#django.forms.Form) to the same URL as we're
displaying an object using [`DetailView`](/ja/3.1/ref/class-based-views/flattened-index/#DetailView).

### `DetailView` で `FormMixin` を使用する

Think back to our earlier example of using [`View`](/ja/3.1/ref/class-based-views/flattened-index/#View) and
[`SingleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin) together. We were
recording a user's interest in a particular author; say now that we want to
let them leave a message saying why they like them. Again, let's assume we're
not going to store this in a relational database but instead in
something more esoteric that we won't worry about here.

At this point it's natural to reach for a [`Form`](/ja/3.1/ref/forms/api/#django.forms.Form) to
encapsulate the information sent from the user's browser to Django. Say also
that we're heavily invested in [REST](https://en.wikipedia.org/wiki/Representational_state_transfer), so we want to use the same URL for
displaying the author as for capturing the message from the
user. Let's rewrite our `AuthorDetailView` to do that.

We'll keep the `GET` handling from [`DetailView`](/ja/3.1/ref/class-based-views/flattened-index/#DetailView), although
we'll have to add a [`Form`](/ja/3.1/ref/forms/api/#django.forms.Form) into the context data so we can
render it in the template. We'll also want to pull in form processing
from [`FormMixin`](/ja/3.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin), and write a bit of
code so that on `POST` the form gets called appropriately.

> **Note**
>
> We use [`FormMixin`](/ja/3.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin) and implement
> `post()` ourselves rather than try to mix [`DetailView`](/ja/3.1/ref/class-based-views/flattened-index/#DetailView) with
> [`FormView`](/ja/3.1/ref/class-based-views/flattened-index/#FormView) (which provides a suitable `post()` already) because
> both of the views implement `get()`, and things would get much more
> confusing.

新しい `AuthorDetail` は次のようになります。

```
# CAUTION: you almost certainly do not want to do this.
# It is provided as part of a discussion of problems you can
# run into when combining different generic class-based view
# functionality that is not designed to be used together.

from django import forms
from django.http import HttpResponseForbidden
from django.urls import reverse
from django.views.generic import DetailView
from django.views.generic.edit import FormMixin
from books.models import Author

class AuthorInterestForm(forms.Form):
    message = forms.CharField()

class AuthorDetail(FormMixin, DetailView):
    model = Author
    form_class = AuthorInterestForm

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

    def post(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return HttpResponseForbidden()
        self.object = self.get_object()
        form = self.get_form()
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

    def form_valid(self, form):
        # Here, we would record the user's interest using the message
        # passed in form.cleaned_data['message']
        return super().form_valid(form)
```

`get_success_url()` provides somewhere to redirect to, which gets used
in the default implementation of `form_valid()`. We have to provide our
own `post()` as noted earlier.

### より良い解決策

The number of subtle interactions between
[`FormMixin`](/ja/3.1/ref/class-based-views/mixins-editing/#django.views.generic.edit.FormMixin) and [`DetailView`](/ja/3.1/ref/class-based-views/flattened-index/#DetailView) is
already testing our ability to manage things. It's unlikely you'd want to
write this kind of class yourself.

In this case, you could write the `post()` method yourself, keeping
[`DetailView`](/ja/3.1/ref/class-based-views/flattened-index/#DetailView) as the only generic functionality, although writing
[`Form`](/ja/3.1/ref/forms/api/#django.forms.Form) handling code involves a lot of duplication.

Alternatively, it would still be less work than the above approach to
have a separate view for processing the form, which could use
[`FormView`](/ja/3.1/ref/class-based-views/generic-editing/#django.views.generic.edit.FormView) distinct from
[`DetailView`](/ja/3.1/ref/class-based-views/flattened-index/#DetailView) without concerns.

### もう一つのより良い解決策

What we're really trying to do here is to use two different class
based views from the same URL. So why not do just that? We have a very
clear division here: `GET` requests should get the
[`DetailView`](/ja/3.1/ref/class-based-views/flattened-index/#DetailView) (with the [`Form`](/ja/3.1/ref/forms/api/#django.forms.Form) added to the context
data), and `POST` requests should get the [`FormView`](/ja/3.1/ref/class-based-views/flattened-index/#FormView). Let's
set up those views first.

The `AuthorDisplay` view is almost the same as [when we
first introduced AuthorDetail](/ja/3.1/topics/class-based-views/generic-display/#generic-views-extra-work); we have to
write our own `get_context_data()` to make the
`AuthorInterestForm` available to the template. We'll skip the
`get_object()` override from before for clarity:

```
from django import forms
from django.views.generic import DetailView
from books.models import Author

class AuthorInterestForm(forms.Form):
    message = forms.CharField()

class AuthorDisplay(DetailView):
    model = Author

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['form'] = AuthorInterestForm()
        return context
```

Then the `AuthorInterest` is a [`FormView`](/ja/3.1/ref/class-based-views/flattened-index/#FormView), but we have to bring in
[`SingleObjectMixin`](/ja/3.1/ref/class-based-views/mixins-single-object/#django.views.generic.detail.SingleObjectMixin) so we can find the
author we're talking about, and we have to remember to set `template_name` to
ensure that form errors will render the same template as `AuthorDisplay` is
using on `GET`:

```
from django.http import HttpResponseForbidden
from django.urls import reverse
from django.views.generic import FormView
from django.views.generic.detail import SingleObjectMixin

class AuthorInterest(SingleObjectMixin, FormView):
    template_name = 'books/author_detail.html'
    form_class = AuthorInterestForm
    model = Author

    def post(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return HttpResponseForbidden()
        self.object = self.get_object()
        return super().post(request, *args, **kwargs)

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

Finally we bring this together in a new `AuthorDetail` view. We
already know that calling [`as_view()`](/ja/3.1/ref/class-based-views/base/#django.views.generic.base.View.as_view) on
a class-based view gives us something that behaves exactly like a function
based view, so we can do that at the point we choose between the two subviews.

You can pass through keyword arguments to
[`as_view()`](/ja/3.1/ref/class-based-views/base/#django.views.generic.base.View.as_view) in the same way you
would in your URLconf, such as if you wanted the `AuthorInterest` behavior
to also appear at another URL but using a different template:

```
from django.views import View

class AuthorDetail(View):

    def get(self, request, *args, **kwargs):
        view = AuthorDisplay.as_view()
        return view(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        view = AuthorInterest.as_view()
        return view(request, *args, **kwargs)
```

This approach can also be used with any other generic class-based
views or your own class-based views inheriting directly from
[`View`](/ja/3.1/ref/class-based-views/flattened-index/#View) or [`TemplateView`](/ja/3.1/ref/class-based-views/flattened-index/#TemplateView), as it keeps the different
views as separate as possible.

## 単純な HTML を超える

クラスベースビューが役に立つのは、同じことを何度もしたい場合です。例えばAPIを作成している場合、全てのビューはレンダリングされたHTMLではなくJSONを返す必要があります。

全てのビューで利用するために、 JSONへの変換処理をするmixinクラスを作成することができます。

たとえば、JSONのmixinは以下のようになるでしょう。

```
from django.http import JsonResponse

class JSONResponseMixin:
    """
    A mixin that can be used to render a JSON response.
    """
    def render_to_json_response(self, context, **response_kwargs):
        """
        Returns a JSON response, transforming 'context' to make the payload.
        """
        return JsonResponse(
            self.get_data(context),
            **response_kwargs
        )

    def get_data(self, context):
        """
        Returns an object that will be serialized as JSON by json.dumps().
        """
        # Note: This is *EXTREMELY* naive; in reality, you'll need
        # to do much more complex handling to ensure that arbitrary
        # objects -- such as Django model instances or querysets
        # -- can be serialized as JSON.
        return context
```

> **Note**
>
> Djangoモデルやクエリセットを正しくJSONに変換する方法についての詳細は :doc:/topics/serialization\`ドキュメントを参照してください。

このmixinは [`render_to_response()`](/ja/3.1/ref/class-based-views/mixins-simple/#django.views.generic.base.TemplateResponseMixin.render_to_response) と同じ引数をもつ `render_to_json_response()` メソッドを提供します。これを使用するには、たとえば `TemplateVIew` へ取り入れ、 `render_to_response()` をオーバーライドして代わりに `render_to_json_response()` を呼び出す必要があります。

```
from django.views.generic import TemplateView

class JSONView(JSONResponseMixin, TemplateView):
    def render_to_response(self, context, **response_kwargs):
        return self.render_to_json_response(context, **response_kwargs)
```

Equally we could use our mixin with one of the generic views. We can make our
own version of [`DetailView`](/ja/3.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView) by mixing
`JSONResponseMixin` with the
[`BaseDetailView`](/ja/3.1/ref/class-based-views/generic-display/#django.views.generic.detail.BaseDetailView) -- (the
[`DetailView`](/ja/3.1/ref/class-based-views/generic-display/#django.views.generic.detail.DetailView) before template
rendering behavior has been mixed in):

```
from django.views.generic.detail import BaseDetailView

class JSONDetailView(JSONResponseMixin, BaseDetailView):
    def render_to_response(self, context, **response_kwargs):
        return self.render_to_json_response(context, **response_kwargs)
```

このビューはレスポンスの作成を除いて、他の:class:~django.views.generic.detail.DetailView\`と同じように記述され、同じように動作します。

さらに応用したければ、HTTPヘッダーやクエリ引数などのHTTPリクエストのプロパティに応じてHTMLとJSONの両方を返すことができる、:class:~django.views.generic.detail.DetailView\`のサブクラスを作成することができます。
JSONResponseMixin\`\`と:class:~django.views.generic.detail.SingleObjectTemplateResponseMixin\`クラスのb両方を取り入れ、:func:~django.views.generic.base.TemplateResponseMixin.render\_to\_response()\`をオーバーライドしてレスポンスの種類によってレンダリングメソッドを切り替えるようにします。

```
from django.views.generic.detail import SingleObjectTemplateResponseMixin

class HybridDetailView(JSONResponseMixin, SingleObjectTemplateResponseMixin, BaseDetailView):
    def render_to_response(self, context):
        # Look for a 'format=json' GET argument
        if self.request.GET.get('format') == 'json':
            return self.render_to_json_response(context)
        else:
            return super().render_to_response(context)
```

Pythonのメソッド多重定義に関する仕様により、super().render\_to\_response(context)\`\`の呼び出しは:class:~django.views.generic.base.TemplateResponseMixin\`に実装された:meth:~django.views.generic.base.TemplateResponseMixin.render\_to\_response()\`メソッドを呼び出します。
