[DRF] Generic Viewsの使い方

Python Django
  • 2023/04/02

以前、APIViewを継承してgetやpostメソッドの実装について確認しました。
今回はGeneric Viewsを継承して各メソッドの動作を確認してみたいと思います。
Generic Viewsには一般的なGET/POST/PUT/DELETEの機能が実装されているため、これらを継承することで自分でメソッドの実装を書く必要がなくなります。
APIがどのメソッドを許可するのかによって継承するクラスが異なります。
それぞれの動作を確認していきます。

Model, Serializerの準備

Viewを記述する前に、ModelとSerializerを作成します。
ModelSerializerについては以前の記事でViewへの記述方法などを説明しました。
Generic ViewsでもModelSerializerを使用できるので、今回もこちらを作成して使ってみます。
まずModelを作成します。
今回も本のタイトルと著者を記録するBookモデルを使用します。

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=50)
    author = models.CharField(max_length=20)

    def __str__(self):
        return self.title

このBookモデルに対するModelSerializerは下記になります。

from rest_framework import serializers
from .models import Book

class BookModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['id', 'title', 'author']

ListAPIView

まずはListAPIViewを継承します。
ListAPIViewはGETメソッドをもつクラスで、データの一覧を返します。
Bookモデルの一覧を返すViewを作成します。
Generic Viewsを継承するためにrest_framwork.genericsをimportします。

from rest_framework import generics
from .models import Book
from .serializers import BookModelSerializer

class BookListView(generics.ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

上記の通り、querysetとserializer_classに値を設定しています。
querysetには、Viewが返すオブジェクトを設定します。
今回はBookモデルの全データを返すので、Book.objects.all()を設定しています。
querysetに値を設定する方法として、get_queryset()をオーバーライドする方法もあります。
例えば、全データを返すのではなく、渡されたリクエストパラメータに応じてデータをフィルターする場合などに、get_queryset()をオーバーライドします。

def get_queryset(self):
    return TargetRecord.objects.filter(author=self.request.GET.get('author'))

serializer_classにはSerializerを設定します。
この設定をすることでSerializerがバリデーションとデシリアライズを行ってくれます。
querysetと同様に、get_serializer_class()をオーバーライドすることでカスタマイズすることも可能です。

それでは、URLを設定してブラウザで動作を確認します。

urlpatterns = [
    path('list/', BookListView.as_view()),
]

image.png

Bookモデルの全データが表示されることを確認できました。

複雑なフィルターなどがなければ、他のViewも同じようにquerysetとserializer_classを指定するだけで使うことができます。
以降、他のViewについても簡単に動作を見ていきます。

RetrieveAPIView

RetrieveAPIViewは、指定したプライマリーキーのデータに対してGETメソッドを呼び出すViewです。

class BookView(generics.RetrieveAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

URLは下記のようにプライマリーキーを指定します。

path('list/<int:pk>/', BookView().as_view()),

ブラウザでid=2のデータを呼び出すと、下記のようになります。 image.png

CreateAPIView

POSTメソッドを持つViewです。
実装は下記のようになります。

class BookCreateView(generics.CreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

ブラウザでの表示は下記になります。 image.png

GETメソッドが許可されていないので既存データは確認できませんが、新規データを登録できるようになっています。
APIViewを継承してpostメソッドをオーバーライドしていた時との違いは、POSTするデータをJSON形式で記述する必要がなく、それぞれのカラムの値を入力するフィールドが用意されていることです。
下記のデータをPOSTしてみます。 image.png

201のステータスコードが返り、登録に成功したことが確認できました。 image.png

/listにアクセスし、全データを確認してみます。 image.png 先ほど登録したid=8のデータが表示されることを確認できました。

UpdateAPIView

PUT/PATCHメソッドを持つViewです。
実装は下記になります。

class BookUpdateView(generics.UpdateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

ブラウザでid=8のデータにアクセスしてみます。
image.png

POSTと同じようにデータを入力できるフォームが用意されています。
下記のようにデータを書き換えてみます。
image.png

データの更新を確認できました。
image.png

/listにアクセスし、全データを確認してみます。
image.png id=8のデータが更新されていることを確認できました。

DestroyAPIView

DELETEメソッドを持つViewです。
実装は下記になります。

class BookDeleteView(generics.DestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

ブラウザで先ほど作成したid=8のデータにアクセスしてみます。 image.png

この時点ではまだDELETEメソッドが実行されていないので、DELETEボタンを押してメソッドを呼び出します。
ステータスコード204が返り、削除に成功しました。
image.png

/listにアクセスし、データ一覧を確認してみます。 image.png

id=8のデータが表示されないことを確認できました。

ListCreateAPIView

ここからは複数のメソッドを持つViewについて確認していきます。
まずはGET/POSTメソッドを持つListCreateAPIViewです。
実装はこれまでのViewと同様です。

class BookGetPostView(generics.ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

ブラウザで確認します。 image.png 全データとPOSTするフォームが表示されました。

もう一度同じデータを登録してみます。 image.png

POSTに成功し、データの登録ができました。 image.png

GETボタンを押してみます。 image.png

登録したid=9のデータが表示されました。

RetrieveUpdateAPIView

RetrieveUpdateAPIViewはGET/PUTメソッドを持つViewです。
ブラウザでの動作についてはこれまでと同じですので、詳細は省略します。

実装

class BookGetPutView(generics.RetrieveUpdateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

ブラウザ image.png

RetrieveDestroyAPIView

RetrieveDestroyAPIViewはGET/DELETEメソッドを持つViewです。

実装

class BookGetDeleteView(generics.RetrieveDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

ブラウザ image.png

RetrieveUpdateDestroyAPIView

RetrieveUpdateDestroyAPIViewは、GET/PUT/PATCH/DELETEメソッドを持つViewです。

実装

class BookGetPutDeleteView(generics.RetrieveUpdateDestroyAPIView):
    queryset = Book.objects.all()
    serializer_class = BookModelSerializer

ブラウザ image.png

まとめ

全てのGeneric Viewsについて動作を確認してみました。
許可するメソッドに応じて適切にこれらのViewクラスを使い分けていきたいと思います。

参考文献

Generic views - Django REST framework

Profile

Hotaru

メーカーで組み込み系のソフトウェアやファームウェアの開発をしています。

仕事では主にC言語、Python、C#を使っています。 ...もっと見る