Django の REST framework で API を作って JSON を返す方法

Django で REST API を作る場合、大まかな流れとしては Python 仮想環境内に作った Django プロジェクトに API 用の独自のアプリケーションを作り、その中にシリアライザ(データを JSON 形式に変換する機能)と View を作ります。

ここで紹介するのは単純にテーブル内のデータを全て GET で抽出してそのまま JSON 形式で返すだけのものです。POST や DELETE などは触れていません。

  1. 下準備
    • API 用 Django アプリケーションの作成
    • djangorestframework のインストール
    • urls.py の設定
    • models.py にモデルを記述
  2. シリアライザの作成
  3. ビューの作成
    • class based view の場合
    • function based view の場合
  4. 動作確認

下準備

API 用 Django アプリケーションの作成

API 用にアプリケーション「api」を作成します。

% python manage.py startapp api

settings.py の INSTALLED_APPS に追加します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'api.apps.ApiConfig', # 追記
]

djangorestframework のインストール

コマンド「pip install djangorestframework」を実行します。

% pip install djangorestframework
Collecting djangorestframework
  Downloading djangorestframework-3.12.4-py3-none-any.whl (957 kB)
     |████████████████████████████████| 957 kB 4.1 MB/s 
Requirement already satisfied: django>=2.2 in /Users/ユーザー名/PythonProjects/仮想環境名/lib/python3.8/site-packages (from djangorestframework) (3.2)
Requirement already satisfied: pytz in /Users/ユーザー名/PythonProjects/仮想環境名/lib/python3.8/site-packages (from django>=2.2->djangorestframework) (2021.1)
Requirement already satisfied: sqlparse>=0.2.2 in /Users/ユーザー名/PythonProjects/仮想環境名/lib/python3.8/site-packages (from django>=2.2->djangorestframework) (0.4.1)
Requirement already satisfied: asgiref<4,>=3.3.2 in /Users/ユーザー名/PythonProjects/仮想環境名/lib/python3.8/site-packages (from django>=2.2->djangorestframework) (3.3.4)
Installing collected packages: djangorestframework
Successfully installed djangorestframework-3.12.4
%

settings.py の INSTALLED_APPS に追加します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    'api.apps.ApiConfig',
    'rest_framework', # 追記
]

urls.py の設定

アプリケーション「api」ディレクトリに url.py を作成した上で、プロジェクトレベルの url.py から参照します。

from django.contrib import admin
from django.urls import path, include # 追記

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('api.urls')), # 追記
]

models.py にモデルを記述

API で使用したいモデルを models.py に記述します。

今回すでにデータベース上にテーブルを用意してあるのでコマンド「python manage.py inspectdb テーブル名」でモデル情報を抽出します。

% python manage.py inspectdb yt_analysis_07
# This is an auto-generated Django model module.
# You'll have to do the following manually to clean this up:
#   * Rearrange models' order
#   * Make sure each model has one field with primary_key=True
#   * Make sure each ForeignKey and OneToOneField has `on_delete` set to the desired behavior
#   * Remove `managed = False` lines if you wish to allow Django to create, modify, and delete the table
# Feel free to rename the models, but don't rename db_table values or field names.
from django.db import models


class YtAnalysis07(models.Model):
    channel_id = models.CharField(max_length=40, blank=True, null=True)
    channel_name = models.TextField(blank=True, null=True)
    view_count = models.BigIntegerField(blank=True, null=True)
    like_count = models.IntegerField(blank=True, null=True)
    dislike_count = models.IntegerField(blank=True, null=True)
    favorite_count = models.IntegerField(blank=True, null=True)
    comment_count = models.IntegerField(blank=True, null=True)
    video_count = models.IntegerField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'yt_analysis_07'
% 

クラス文を models.py にコピーしますが、その際に 1 つ「primary_key=True」のフィールドを持つ必要があるそうです。

シリアライザの作成

Python のリスト・辞書形式のデータを JSON に変換するためのシリアライザを作成します。

アプリケーションフォルダ(今回は api/ )に「serializers.py」というファイルを作成します。

from rest_framework import serializers
from .models import YtAnalysis07 # モデルをインポート

class APISerializer(serializers.ModelSerializer):
    class Meta:
        model = YtAnalysis07 # 使用するモデル
        fields = '__all__' # 処理対象にするフィールド(今回は全項目)

ビューの作成

API のビューを作成します。ざっくり言うとモデルからデータを抽出し、シリアライザに渡して JSON に変換し、その JSON データをレスポンスとして返します。

class based view の場合

from rest_framework import viewsets
from .serializers import APISerializer
from .models import YtAnalysis07

class DataListView(viewsets.ModelViewSet):
    queryset = YtAnalysis07.objects.all() # モデルからデータを抽出するクエリセット
    serializer_class = APISerializer # 使用するシリアライザ

urls.py の設定は下記の様にします。

from django.urls import path
from . import views

app_name = 'api'
urlpatterns = [
    path('data-list/', views.DataListView.as_view({'get': 'list'}), name="data-list"),
]

function based view の場合

from rest_framework.decorators import api_view
from rest_framework.response import Response
from .serializers import APISerializer
from .models import YtAnalysis07

@api_view(['GET']) # GET のみに対応
def dataList(request):
    api_data = YtAnalysis07.objects.all() # モデルからデータを抽出する
    serializer = APISerializer(api_data, many=True) # シリアライザにデータを渡す
    return Response(serializer.data) シリアル可されたデータを return で返す

urls.py の設定は下記の様にします。

from django.urls import path
from . import views

app_name = 'api'
urlpatterns = [
    path('data-list/', views.dataList, name="data-list"),
]

動作確認

設定した URL をブラウザに打ち込むと下記の様な画面が表示されます。JSON データも見えます。

ブラウザで URL を叩くと上記の様な画面で表示されますが、例えばターミナルで URL を requests.get すると下記の様に JSON 形式のデータだけが返ってきます。

>>> import requests
>>> r = requests.get('http://127.0.0.1:8000/api/data-list/')
>>> r.text
'[{"channel_id":"UCLkAepWjdylmXSltofFvsYQ","channel_name":"BANGTANTV","view_count":22423409,"like_count":7325674,"dislike_count":20936,"favorite_count":0,"comment_count":381315,"video_count":9},{"channel_id":"UCE_M8A5yxnLfW0KghEeajjw","channel_name":"Apple","view_count":19044060,"like_count":600159,"dislike_count":21023,"favorite_count":0,"comment_count":0,"video_count":10},

これを Django のテンプレートから JavaScript で呼び出すなどして活用します。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です