DRF(django-rest-framework)のAPIViewでページネーションを使う
概要
DRFのAPIViewでページネーションを使うときに思ったより苦戦したでその時のメモ。
動くコードは以下にコミットしてあります。(ファイル名が雑なのは気にしないでください)
注意事項
以下のライブラリバージョンで動作確認しています。
Django==4.1
djangorestframework==3.13.1
djangoプロジェクトの作成
まずは、djangoのプロジェクト作成をします。
ここのやり方はそれぞれの環境に合わせて適宜作成してください。
以下のコマンドはMacで実行しています。
$ mkdir drf_pagination_apiview
$ cd drf_pagination_apiview
$ python -m venv .venv
$ source .venv/bin/activate
$ pip instal django djangorestframework django-cors-headers
$ django-admin startproject config .
$ python manage.py startapp myapp
djangoの初期設定
settings.py
django-rest-framework、corsheaders、appの設定を追記します。
~~~ 省略 ~~~
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# 以下を追記
'corsheaders',
'rest_framework',
'myapp',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware', # 追記
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
# 追記
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 10, # デフォルトで10レコードずつ取得
}
~~~ 省略 ~~~
config/urls.pyを編集
myappで実装するviewsをあらかじめimportしておく。
from django.contrib import admin
from django.urls import path, include # includeを追記
from myapp.urls import app_urls # 追記
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(app_urls)), # 追記
]
myappの設定
ここにAPIViewでページネーションをする実装をしていきます。
models.pyを編集
今回のサンプルで使用するモデルを作成。
特に意味はないが2つカラムを作ってみた。
from django.db import models
class DRFPaginationModel(models.Model):
col1 = models.CharField(max_length=30)
col2 = models.CharField(max_length=30)
def __str__(self):
return self.col1
serializers.pyの作成
ModelSerializerを使ってdjangoのモデルからシリアライザを作成
from rest_framework import serializers
from myapp.models import DRFPaginationModel
class DRFPaginationSerializer(serializers.ModelSerializer):
class Meta:
model = DRFPaginationModel
fields = "__all__"
views.pyを編集
ここが重要な部分。
APIView
とLimitOffsetPagination
を継承したクラスを作成し、paginate_queryset
に渡すことでページネーションができるらしい。
from rest_framework.views import APIView
from rest_framework.pagination import LimitOffsetPagination # ページネーションのクラス
from myapp.models import DRFPaginationModel
from myapp.serializers import DRFPaginationSerializer
class DRFPaginationSampleView(APIView, LimitOffsetPagination):
def get(self, request):
# 今回はモデルから全データを取得
q = DRFPaginationModel.objects.all()
results = self.paginate_queryset(q, request, view=self)
t = DRFPaginationSerializer(results, many=True)
# t.dataでpaginationされたデータにアクセスできる
res = {
"data": t.data,
"test": "このように好きな値とかもセットできる"
}
return self.get_paginated_response(res)
urls.pyを作成
作成したViewをURLで繋ぎこむ。
from django.urls import path, include
from myapp.views import DRFPaginationSampleView
app_urls = [
path("paginationsample/", DRFPaginationSampleView.as_view()),
]
サンプルデータをロード
リポジトリに1000レコードのサンプルデータを用意しているので必要であればロードしてください。
※リポジトリ内のsqliteには予めデータが読み込まれています
$ python manage.py loaddata dump.json
APIを試す
$ python manage.py runserver
以下のURLにアクセス
http://127.0.0.1:8000/api/paginationsample/
今回はsettings.pyにPAGE_SIZEを10と設定したので10件ずつ帰ってくる。
{
"count": 1000,
"next": "http://127.0.0.1:8000/api/paginationsample/?limit=10&offset=10",
"previous": null,
"results": {
"data": [
{
"id": 1,
"col1": "C1-0",
"col2": "C2-0"
},
{
"id": 2,
"col1": "C1-1",
"col2": "C2-1"
},
~~~ 省略 ~~~
{
"id": 9,
"col1": "C1-8",
"col2": "C2-8"
},
{
"id": 10,
"col1": "C1-9",
"col2": "C2-9"
}
],
"test": "このように好きな値とかもセットできる"
}
}
参考
クエリパラメータを書き換えると任意の位置から指定したレコード数取得できる
- limit・・・取得するレコード数
- offset・・・取得を開始する位置
limitとoffsetの例
- 15レコード目から14件取得したい
- limit=14
- offset=15
最後に
DRFはシンプルなAPIは簡単に作れる反面、細かいことをやろうとするとよく苦戦するので、最小限で動くサンプルは今後も残して行きたいなと思います。
Discussion