Django REST FRAMEWORK Tutorial 11 -- SnippetList を Mixin を使って短く書き換える
Published: 2022-05-08 17:20:04


## メリット

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

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

```py
    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)
```

これが

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

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)
```

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

---

## SnippetList を Generics と Mixins を使って書く

```py
from rest_framework import mixins
from rest_framework import generics
```

mixins, generics, を import

```py
class SnippetList(mixins.ListModelMixin,
                  mixins.CreateModelMixin,
                  generics.GenericAPIView):
```

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

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

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

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

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)
```

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

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

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

と推測する。

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

---

## SnippetDetail で Generics と　Mixin を使う

```py
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)
```

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

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

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

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

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

---

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

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

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

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


class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
```

generics.ListCreateAPIView で List, Create

generics.RetrieveUpdateDestroyAPIView
で Retrieve, Update, Destroy, 

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

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

---

## まとめ

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

```py
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)
```

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

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

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