LoginSignup
1
2

Django REST FrameworkでAPIを作成してみた

Last updated at Posted at 2023-10-07

背景

以前からDjangoにおけるWebアプリケーション作成において、ReactやFlutterなどのフロントエンドのフレームワークとの結合を考えております。
今回は、それに先立ちフロントエンドとバックエンドとのやりとりをDjango REST Frameworkを利用したRESTful APIで行なうために学習した記録です。

先人たちの知恵をお借りするなどして解決できたことを、この場をお借りして感謝するとともに、大変恐縮ですが自分のメモとして、こちらへまとめておきます。

はじめに

チグサさんのブログ:「チグサウェブ」の記事を参考に、Django REST Frameworkを利用して、RESTful APIを作成してみました。
大変分かりやすくまとまっており、これから学習する方にもオススメです。

今回、チグサさんの記事と異なり、dockerでの環境構築やDjangoで利用するデータベースの変更は省いています。

今回使用する環境等のバージョン

  • Windows 11 Pro 22H2
  • Python 3.12.0
  • Django 4.2.6
  • Django REST Framework 3.14.0
  • SQLite 3.43.1

そもそもAPIとは?

Application Programming Interfaceの略。
今回作成するのはHTTPやHTTPS通信でデータのやり取りを行うことができる、Web APIです。

Django REST Frameworkとは?

Django REST Framework (DRF)とはRESTful API開発に特化したDjangoのフレームワークです。
DRFを使うことでよりRESTfulなWebアプリケーションを作成することができます。

RESTful APIとはRESTという原則を守っているHTTP呼び出しインターフェースのことです。
Django REST Frameworkを使用することにより、Djangoフレームワークで簡単にAPIの実装ができる優れもの。
バックエンドのAPIサーバーを実装する際に大変便利です。

1.python仮想環境の構築

Python環境に、venvにより仮想環境を構築します。(すでにPython実行環境は構築済みの前提です。)
以下のコマンドを実行します。

python -m venv venv

2つめの「venv」は仮想環境名ですので、任意で指定してください。

ディレクトリ構成
rootvenvIncludeLibScriptspyvenv.cfg

以下のコマンドで仮想環境を有効にします。

cd venv\Scripts
activate.bat

# rootディレクトリに戻る
(venv) cd ../..

以下のコマンドでpipをupgradeします。

(venv) python -m install --upgrade pip

2.Djangoのインストール

以下のコマンドでdjangoをインストールします。

(venv) pip install django

3.Djangoプロジェクトの作成

以下のコマンドで、Djangoプロジェクトを作成します。
最後に「.」(ドット)を付けることで、同じ階層にプロジェクトファイルを作成しています。

(venv) django-admin startproject djangoApiApp .

「djangoApiApp」はプロジェクト名ですので、任意で指定してください。

ディレクトリ構成
rootdjangoApiApp  # 追加
__pycache____init__.pyasgi.pysettings.pywsgi.pyvenvIncludeLibScriptspyvenv.cfg
db.sqlite3
manage.py

4.Djangoのデータベースの設定

デフォルトでsqlite3が指定されていますので、今回はこのまま使います。

djangoApiApp/settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

MySQLやPostgreSQLに変更するには、Djangoの公式ドキュメントをご参照ください。

言語とタイムゾーンの項目を修正します。

djangoApiApp/settings.py
LANGUAGE_CODE = 'ja'       # 修正

TIME_ZONE = 'Asia/Tokyo'   # 修正

設定ファイルについては、SECRET_KEYやデータベースの接続情報などの機密情報が含まれます。
GitHubの公開リポジトリなどに、そのままプッシュしてしまうのは大変危険です。

今回は、これらを管理するツールとして便利なdjango-environを使います。

django-environのインストール

django-environは外部モジュールなのでインストールする必要があります。
Djangoアプリケーションが動作しているPython環境で、次のコマンドを実行します。

(venv) pip install django-environ

インストールはこれだけです。

.envファイルの作成と記述

manage.pyと同じ階層(今回の構成ではdjandoプロジェクト直下)に「.env」という名前でファイルを作成します。

ディレクトリ構成
rootdjangoApiApp__pycache____init__.pyasgi.pysettings.pywsgi.pyvenvIncludeLibScriptspyvenv.cfg
.env              # 追加
db.sqlite3
manage.py

このファイルに環境変数などの機密情報を分離します。

.env
SECRET_KEY=django-insecure-*************************************
DEBUG=True

DATABASE_ENGINE=django.db.backends.sqlite3  # 使用するDBのエンジン(sqlite3ならdjango.db.backends.sqlite3)
DATABASE_DB=db.sqlite3                      # データベース名(sqlite3ならdb.sqlite3)
DATABASE_USER=django_user                   # defaultのままで可
DATABASE_PASSWORD=password                  # defaultのままで可
DATABASE_HOST=localhost                     # defaultのままで可
DATABASE_PORT=5432                          # defaultのままで可

=の前後に半角スペースが入ったり、文字列をシングルクォーテーションで囲っていたりするとエラーになるので注意しましょう。

他にも、APIキーなど他人に知られてはいけない情報は、ソースコードに含めないように気を付けましょう。

settings.pyで環境変数を呼び出す

.envファイルに環境変数をsettings.pyで呼び出します。

djangoApiApp/settings.py
import os                       # 追加
import environ                  # 追加
 
env = environ.Env()             # 追加
env.read_env('.env')            # 追加
 
SECRET_KEY = env('SECRET_KEY')  # 修正
DEBUG = env('DEBUG')            # 修正
 
DATABASES = {
    'default': {
        'ENGINE': env.get_value('DATABASE_ENGINE', default='django.db.backends.sqlite3'),      # 修正
        'NAME': env.get_value('DATABASE_DB', default=os.path.join(BASE_DIR, 'db.sqlite3')),    # 修正
        'USER': env.get_value('DATABASE_USER', default='django_user'),                         # 追加
        'PASSWORD': env.get_value('DATABASE_PASSWORD', default='password'),                    # 追加
        'HOST': env.get_value('DATABASE_HOST', default='localhost'),                           # 追加
        'PORT': env.get_value('DATABASE_PORT', default='5432'),                                # 追加
    }
}

これだけ!

5.Django REST Frameworkのインストール

Djangoアプリケーションが動作しているPython環境に、Django REST Frameworkをインストールします。

(venv) pip install djangorestframework

6.アプリ追加と設定

以下のコマンドで、Djangoプロジェクトにアプリケーションを追加します。
商品マスターを想定したアプリケーションとして、APIを実装します。

(venv) python manage.py startapp products
ディレクトリ構成
rootdjangoApiApp__pycache____init__.pyasgi.pysettings.pywsgi.pyproducts       # 追加
__pycache__migtarions__init__.pyadmin.pyapps.pymodels.pytests.pyviews.pyvenvIncludeLibScriptspyvenv.cfg
.env
db.sqlite3
manage.py

djangoプロジェクトのsettings.pyに、アプリケーションを追加します。

djangoApiApp/settings.py
INSTALLED_APPS = [
...
    'rest_framework',  # 追加
    'products',        # 追加
]

Django REST Frameworkを使えるように、「rest_framework」を指定します。

7.Modelとテーブルの作成

テーブル定義に合わせたモデルを作成します。
今回は商品を想定したモデルとしました。

products/models.py
# 以下を追加
class Product(models.Model):

    name = models.CharField(max_length=200)
    price = models.IntegerField()

以下のコマンドでマイグレーションファイルを作成します。

(venv) python manage.py makemigrations products

以下のファイルが自動で作成されます。

products/migrations/0001_initial.py
# Generated by Django 4.0.3 on 2022-04-06 13:44

from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Product',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('name', models.CharField(max_length=200)),
                ('price', models.IntegerField()),
            ],
        ),
    ]

以下のコマンドでマイグレーションを実行し、テーブルを作成します。

(venv) python manage.py migrate

管理画面での確認

Djangoの管理画面から確認してみましょう。
まずは、管理画面にログインするためのユーザを作成します。

以下のコマンドを実行します。

(venv) python manage.py createsuperuser

ユーザ名、メールアドレス、パスワードを聞かれますので、任意で指定してください。

以下のコマンドで開発サーバーを起動します。

(venv) python manage.py runserver

以下のURLにアクセスします。

http://localhost:8000/admin/

管理画面が表示されますので、先ほど作成したユーザでログインします。
スクリーンショット 2023-10-07 210240.png

管理画面にアクセスすることができました。
スクリーンショット 2023-10-07 181116.png

今回テーブルを作成した商品マスタを編集できるようするため、以下のファイルを修正します。

products/admin.py
from django.contrib import admin

# Register your models here.

from .models import Product   # 追加

admin.site.register(Product)  # 追加

画面を更新すると、商品テーブルのマスタメンテが追加されました。
スクリーンショット 2023-10-07 181303.png

ここから新規登録などができます。
スクリーンショット 2023-10-07 181410.png

一覧を表示すると、「xx object (1)」のように表示されます。
スクリーンショット 2023-10-07 181428.png

名前が表示されるように、モデルを修正します。

products/models.py
from django.db import models

# Create your models here.

class Product(models.Model):

    name = models.CharField(max_length=200)
    price = models.IntegerField()

    # 以下を追加
    def __str__(self):
        return self.name

画面を更新すると、一覧に名前が表示されるようになりました!
スクリーンショット 2023-10-07 181538.png

管理画面を通じてAPIの動作を確認できます。

8.Serializerクラスの作成

APIでデータのやり取りを行うためのSerializer(シリアライザー)を設定するため、以下のファイルを作成します。

products/serializers.py
# 以下を追加
from rest_framework import serializers
from .models import Product


class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ['name', 'price']
ディレクトリ構成
rootdjangoApiApp__pycache____init__.pyasgi.pysettings.pywsgi.pyproducts__pycache__migtarions__init__.pyadmin.pyapps.pymodels.pyserializers.pytests.pyviews.pyvenvIncludeLibScriptspyvenv.cfg
.env
db.sqlite3
manage.py

Django REST Frameworkの最大の特徴はこのSerializerと言っても過言ではありません。
Serializerについては、「Django REST Framework の特徴(Serializer)」のセクションでの説明が参考になります。

9.Viewの作成

APIの処理を、ViewSetを使用して実装します。
これにより例えば、一覧や詳細データの取得、新規登録、更新、削除などが処理できるようになります。

ここではModelViewSetを使用して、以下のように実装します。

products/views.py
# 以下を上書き
from rest_framework import viewsets
from .models import Product
from .serializers import ProductSerializer


class ProductViewSet(viewsets.ModelViewSet):

    queryset = Product.objects.all()
    serializer_class = ProductSerializer

ModelViewSetは、以下が提供されます。

  • list()
  • retrieve()
  • create()
  • update()
  • partial_update()
  • destroy()

10.URLの追加

APIを呼び出すためのURLをアプリケーションのurls.pyに追加します。
ViewSetをルーターに登録します。

products/urls.py
# 以下を追加
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet

router = DefaultRouter()
router.register('products', ProductViewSet)

urlpatterns = [
    path('', include(router.urls)),
]
ディレクトリ構成
rootdjangoApiApp__pycache____init__.pyasgi.pysettings.pywsgi.pyproducts__pycache__migtarions__init__.pyadmin.pyapps.pymodels.pyserializers.pytests.pyurls.py        # 追加
views.pyvenvIncludeLibScriptspyvenv.cfg
.env
db.sqlite3
manage.py

djangoプロジェクトのurls.pyに追加します。
パスは任意で指定できます。今回は「products/」としました。

djangoApiApp/urls.py
from django.contrib import admin
from django.urls import path, include  # includeを追加

urlpatterns = [
    path('admin/', admin.site.urls),

    # API
    path('products/', include('products.urls')),  # 追加
]

11.APIの確認

API画面

起動していない場合は、以下のコマンドで開発サーバーを起動しましょう。

(venv) python manage.py runserver

以下のURLにアクセスします。

http://localhost:8000/products/

APIを操作するための画面が表示されます。
スクリーンショット 2023-10-07 183500.png

この画面でAPIの確認ができますので大変便利です。

curlコマンドなどでAPIへアクセスすると、実際に使用する際はJSON形式のデータを取得できることが分かります。

(venv) curl http://localhost:8000/products/

# {"products":"http://localhost:8000/products/products/"}

データ編集

一覧を表示するためのURLにアクセスします。

http://localhost:8000/products/products/

一覧のデータと、新規登録のためのフォームが表示されます。
このフォームからデータが追加できますので、試してみてください。
スクリーンショット 2023-10-07 183609.png

詳細を表示するためのURLにアクセスします。(末尾にIDを指定)

http://localhost:8000/products/products/1/

詳細画面が開き、データの編集や削除などができます。
スクリーンショット 2023-10-07 183658.png

これらの画面で操作できることは、APIでも同様にできます。

最低限のコードで、一覧、詳細、新規登録、編集、削除を処理するAPIが実装できました。

12.ViewSetについて

APIView

Modelに紐づかないようなViewも作成できます。
これはAPIViewクラスを使用して、ダミーデータを返却するようなAPIの実装例です。

products/views.py
from rest_framework.views import APIView      # 追加
from rest_framework.response import Response  # 追加

...
# 以下を追加
class ProductDummyApiView(APIView):

    def get(self, request, format=None):
        return Response({"name": "DUMMY!"})   # ダミーデータを返却

APIViewを継承したクラスでは、get、または、postメソッドを定義します。
HTTPのGETでアクセスした場合は、getメソッドが呼ばれます。

URLを追加します。

products/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet, ProductDummyApiView  # ProductDummyApiViewを追加

router = DefaultRouter()
router.register('products', ProductViewSet) 

urlpatterns = [
    path('', include(router.urls)),

    path("dummy/", ProductDummyApiView.as_view()),  # 追加
]

以下のURLにアクセスします。

http://localhost:8000/products/dummy/

ダミーデータを取得できました!
スクリーンショット 2023-10-07 183851.png

api_view

こちらは関数ベースのapi_viewにより、Modelのデータ一覧を表示する処理の実装例です。

products/views.py
from rest_framework.decorators import api_view  # 追加

...
# 以下を追加
@api_view(['GET'])
def product_list(request):

    if request.method == 'GET':
        products = Product.objects.all()
        serializer = ProductSerializer(products, many=True)
        return Response(serializer.data)

ModelViewSetのように、ModelとSerializerを使用して、一覧を返却する処理にします。

URLを追加します。

products/urls.py
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet, ProductDummyApiView, product_list  # product_listを追加

router = DefaultRouter()
router.register('products', ProductViewSet)

urlpatterns = [
    path('', include(router.urls)),
    path("dummy/", ProductDummyApiView.as_view()),

    path('list/', product_list),  # 追加
]

以下のURLにアクセスします。

http://localhost:8000/products/list/

商品の一覧を取得できました!
スクリーンショット 2023-10-07 184221.png

方法はいろいろあれど、実装は簡単にできますので大変便利です。
他にも機能がありますので、公式サイトのドキュメントをご確認ください。


今回のソースコードはGitHubにコミット済みです。


参考


(編集後記)

今回はDjango REST Framework (DRF)を利用して、RESTfulなAPIを作成してみましたが、実装は簡単ですし、画面を通じて確認を行なえるためユーザーフレンドリーです。
バックエンドのAPIを作る際には、選択肢のひとつとしてDRFは大いに利用できるものと分かりました。

ここまでの手順を基に、今後もDjangoによるWebアプリケーション作成をすすめてみます。
皆様の参考になれば幸いです。

今後、フロントエンドにReactまたはFlutterを結合したWebアプリケーションの作成に移りたいのですが、どちらを選ぶかで躊躇している状態でして、両者のメリデメをよく検討した上で決定したいと思います。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2