Django REST Framework で Pagination および並べ替え


はじめに

Django REST Framework で API 作成DRF / django-filter を使ってフィルタリングで API を作成し、フィルタリングも行えるようになった。この記事では、大量のデータに対応できるように Pagination の設定を行い、またデータの並べ替えに対応できるような設定も行った。Pagination - Django REST frameworkFiltering - Django REST framework を参考にした。

Pagination

設定は非常に簡単で、以下をプロジェクトの settings.py に追記するだけ。

settings.py
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 100
}

これで100件ごとでページが分けられる。この設定では、プロジェクト内すべての API が同じ設定となるが、個々で変えたりといろんなカスタムもできるらしい。

データの並べ替え

views.py にて、ViewSet のアトリビュートとして filter_backendsordering_fields を追記することでデータ並べ替えに対応できる。以下で例として用いている views.py はDjango REST Framework で API 作成DRF / django-filter を使ってフィルタリングで作成したものを用いている。コードは以下。

views.py
from .models import Info
from .serializers import InfoSerializer
from rest_framework import viewsets
from rest_framework import filters               # 追加

class InfoViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Info.objects.all()
    serializer_class = InfoSerializer
    filterset_fields = ['id']
    filter_backends = [filters.OrderingFilter]   # 追加
    ordering_fields = ['id']                 # 追加

これにより、id を用いてデータの並べ替えができる。昇順で並べ替えする場合のリクエストは http://localhost:8000/api/info/?ordering=id となる。降順で並べ替えする場合のリクエストはhttp://localhost:8000/api/info/?ordering=-id のようにフィールド名の前に '-' をつける。

(2021/5/6 追記)
DRF / django-filter を使ってフィルタリングでは、settings.py にて 'DEFAULT_FILTER_BACKENDS' を追記することで指定フィールドによるフィルタリングを行っていたが、上記で並べ替え設定をしたところ、フィルタリングが使用できなくなった。おそらく個々の ViewSet での設定が全体設定を上書きしてしまい使用できなくなったと想定される。指定フィールドによるフィルタリングおよび並べ替えの両方を適用する場合は、以下のように個々の ViewSet にて filter_backends を指定してやればよい。

views.py
from .models import Info
from .serializers import InfoSerializer
from rest_framework import viewsets
from django_filters.rest_framework import DjangoFilterBackend         # 追加
from rest_framework import filters

class InfoViewSet(viewsets.ReadOnlyModelViewSet):
    queryset = Info.objects.all()
    serializer_class = InfoSerializer
    filterset_fields = ['id']
    filter_backends = [DjangoFilterBackend, filters.OrderingFilter]   # 追加
    ordering_fields = ['id']

おわりに

API に関する基礎的な設定ができたので、次は React で作成したフロントエンド側から実際に API を叩いてデータを取得できるか試す。