DEV Community

kaede
kaede

Posted on • Edited on

Django REST FRAMEWORK Tutorial 11 -- SnippetList を Mixin を使って短く書き換える

メリット

https://www.django-rest-framework.org/tutorial/3-class-based-views/#using-mixins

Mixin を使うと短くかけるらしい。

    def get(self, request, format=None):
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Enter fullscreen mode Exit fullscreen mode

これが

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)
Enter fullscreen mode Exit fullscreen mode

2行ずつで書けるようになるらしい。正気か?


SnippetList を Generics と Mixins を使って書く

from rest_framework import mixins
from rest_framework import generics
Enter fullscreen mode Exit fullscreen mode

mixins, generics, を import

class SnippetList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):
Enter fullscreen mode Exit fullscreen mode

APIView の代わりに
ListModelMixin, CreateModelMixin, GenericAPIView,
これらを使い

    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
Enter fullscreen mode Exit fullscreen mode

Snippet のオブジェクト全てを queryset 変数に入れて
Snippet のシリアライザーを serializer_class 変数に入れる

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)
Enter fullscreen mode Exit fullscreen mode

get でも post でも *args, **kwargs を使うことによって
queryset と serializer_class を使えるようになると推測する。

get の場合は self.list に
Snippets オブジェクトをシリアライズして全て返す
メソッドが入っていて

post の場合は self.create に
request の中のデータをシリアライズして
エラーハンドリングして結果を返す
メソッドが入っている

と推測する。

動作確認しても、問題なく以前と同じように動いた。


SnippetDetail で Generics と Mixin を使う

class SnippetDetail(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    generics.GenericAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)
Enter fullscreen mode Exit fullscreen mode

SnippetDetail でも同じように Mixin と Generics のモジュール?を引数にとる。

今回は Mixin では Retrieve, Update, Destory, を使う

get が list ではなく、retrieve になっている。

こちらも問題なく動作確認できた。

詳細での取得も上書きも削除も、恐ろしいほど簡単にかけた。


Generics を使って .list, .create や .retreive, .update, .destroy, をまとめる

さらに簡単に書く方法がある。

Mixin すら使わず、Mixin で使っていた相当のメソッドを最初に Generics でまとめてしまう方法だ。

class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
Enter fullscreen mode Exit fullscreen mode

generics.ListCreateAPIView で List, Create

generics.RetrieveUpdateDestroyAPIView
で Retrieve, Update, Destroy,

をモジュールから持ってきてしまえると推測する。

こちらも問題なく動作確認ができた。


まとめ

オブジェクトを取得して
シリアライザにかけて、保存や削除をして〜
と書いていたコードを

class SnippetList(mixins.ListModelMixin,
                  generics.GenericAPIView):

    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)
Enter fullscreen mode Exit fullscreen mode

List, Create などの Mixin と Generics を使うことで
return する箇所に self.list() と書くだけで実装できた。

class SnippetList(generics.ListCreateAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
Enter fullscreen mode Exit fullscreen mode

また、Generics を使い、最初に Mixin の各メソッドを明記することで
return すら書かずに簡略化して書くことが可能だった。

Top comments (0)