DRFマスタリー：Django Rest FrameworkでAPIを効率的に構築する方法

API開発が急速に進化し、その中心には効率とパフォーマンスが求められます。Django Rest Framework（DRF）は、PythonとDjangoのエコシステム内で、これらの要求に応えるための優れたツールです。しかし、そのポテンシャルを最大限に引き出すには、DRFの各コンポーネントとその働きを理解することが不可欠です。

このガイドでは、DRFの主要なコンポーネントであるシリアライザ、ビューセット、ルーティング、認証と権限、ページネーション、そしてカスタムバリデーションに焦点を当て、それぞれの役割と効果的な使用方法を解説します。これらの知識を武器に、あなたも効率的でパワフルなAPIを構築するマスターになりましょう！

## シリアライザ

モデルをJSONに形式に変えるのが**シリアライザ**です。APIをよく使う人にとっては、この説明だけでシリアライザの役割が伝わるでしょう。APIになじみのない人は、「APIというものはJSONという形式で、データの送受信を行っていることが多い」と理解できれば、シリアライズはその第一歩としての役割を持っていることがわかるでしょう。

## ビューセット

**CRUD**とは、作成（Create）、読み取り（Read）、更新（Update）、削除（Delete）というデータベース操作の最低限必要な機能です。ビューセットは、これらCRUDの機能を一気に作成できます。つまり、ビュー（画面）のセット（いくつかの集まり）というわけです。

## ルーティング

ルーティングは、指定されたリクエストを正しいビュー（画面）につなぐための設定を定義します。DRFでのルーティングは、ビューセットが一つのグループなので、一つのビューセットにルーティングすると、CRUDの四つの機能すべてのルーティングが完了してしまう、というイメージです。

## 認証と権限

ビューに対して、簡単に権限や認証も設定できるようになっています。これにより、特定のユーザーだけがアクセスできるように制限するなどの設定が可能です。

## ページネーション

ページネーションがあるということは、大量のデータを効率的に管理する方法が用意されている、というイメージを持っていればいいでしょう。実際には、APIのレスポンスのデータをページに分割して送信できる便利な機能です。

## カスタムバリデーション

カスタムバリデーションは、ユーザーに値を入力させて、その内容に応じたデータを送信する場合に効果を発揮します。つまり、値が正しい入力なのかをチェックする（バリデーション）ルールを、簡単に作れる機能です。

最後復習として、
各項目のコード例と説明も載せておきますので、
上記の解説と照らし合わせてみたりすると府に落としやすいかもしれません。

### シリアライザ

```python
from rest_framework import serializers
from .models import Article

class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = ['id', 'title', 'content', 'author', 'created_at']
```


このコードは、Article モデルのデータを JSON 形式にシリアライズするためのものです。serializers.ModelSerializer を継承して、Article モデルとそのフィールドを指定しています。これにより、Article モデルのインスタンスを JSON に自動的に変換することができます。

### ビューセット
```python
from rest_framework import viewsets
from .models import Article
from .serializers import ArticleSerializer

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
```

ビューセットは、CRUD操作を簡単に実装するためのクラスです。上記のコードでは、Article モデルに対する CRUD 操作を ArticleViewSet として定義しています。queryset でデータの取得、serializer_class でデータのシリアライズ方法を指定しています。

### ルーティング
```python
from rest_framework.routers import DefaultRouter
from .views import ArticleViewSet

router = DefaultRouter()
router.register(r'articles', ArticleViewSet, basename='article')
urlpatterns = router.urls
```

ルーティングは、URL リクエストを適切なビューにマッピングする役割を果たします。上記のコードでは、DefaultRouter を使用して ArticleViewSet を URL パターンに登録しています。これにより、CRUD 操作それぞれに対応する URL が自動的に生成されます。

### 認証と権限
```python
from rest_framework.permissions import IsAuthenticated
from .models import Article
from .serializers import ArticleSerializer
from rest_framework import viewsets

class ArticleViewSet(viewsets.ModelViewSet):
    queryset = Article.objects.all()
    serializer_class = ArticleSerializer
    permission_classes = [IsAuthenticated]  # 認証が必要
```

上記のコードでは、ビューセットに認証を要求する設定を追加しています。permission_classes に IsAuthenticated を指定することで、認証されたユーザーのみがこのビューセットにアクセスできるようになります。

### ページネーション
```python
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response

class CustomPagination(PageNumberPagination):
    page_size = 5

    def get_paginated_response(self, data):
        return Response({
            'links': {
                'next': self.get_next_link(),
                'previous': self.get_previous_link()
            },
            'total': self.page.paginator.count,
            'results': data
        })
```
ページネーションは、大量のデータを効率的に表示するための機能です。上記のコードでは、ページごとに5つのアイテムを表示するカスタムページネーションクラスを作成しています。

### カスタムバリデーション
```python
from rest_framework import serializers

class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = ['id', 'title', 'content', 'author', 'created_at']

    def validate_title(self, value):
        if "badword" in value.lower():
            raise serializers.ValidationError("Inappropriate language detected in title.")
        return value
```

カスタムバリデーションは、入力データの検証ルールをカスタマイズするための機能です。上記のコードでは、validate_title メソッドをオーバーライドして、タイトルに不適切な言葉が含まれていないかをチェックしています。不適切な言葉が含まれている場合は、バリデーションエラーを発生させます。


終わり。

この記事を通して、
DRFの仕組みを少しでも理解いただければ幸いです。
あと、フォローされたらもっと頑張ります！
フォローしてくださいな！