見出し画像

Python×Django+RestFramework×ReactでWebアプリケーション⑧ お買い物アプリ(フロント+バックエンド) Django REST framework➊ ~API Endpoint作成

ノンストップ飯田

1.今回のゴール

Django REST frameworkを使って、API Endpointを作成し外部からデータの取得や更新ができるようにします。

2.Django REST frameworkの仕組み

(1) Djangoの仕組み(振り返り)

前回Djangoで開発したときを振り返ると・・・ざっくり以下のような流れでした。

django概要


ブラウザからリクエストがありレスポンスを返すまでの大まかな流れです。

  1. アクセスがあったurlに応じて、urls.pyで定義したviews.pyの処理が呼ばれます。

  2. views.pyで定義された処理や、テンプレート(HTML)に引き渡すデータをもとにレスポンスを返す。

  3. models.pyで定義されたデータテーブルをviews.pyでの処理や、htmlファイルに埋め込んだフォームから更新したり、取得した情報をviews.pyからhtmlに引き渡して表示させたりする。

こんな感じでした。

(2) Django REST frameworkの仕組み

これまたざっくりですが、Django REST frameworkは以下のような仕組みとなります。

Django REST framework概要

大きな違い目としては・・・

  1. htmlファイルが存在せず、Webブラウザからでなく他システムとやり取り

  2. serializers.pyの存在

まず一番の違い目としては、相手が他システムという点です。APIで、異なるシステムやアプリケーションからのアクセスを許容し、アクセスに対して応答することを実現します。

今回は、この他システムの部分をReactにすることで、フロントエンドはリアクト、バックエンドはDjango REST frameworkという構成を実現しようとしているものです。

serializersは、他システムと連携するにあたり、データの入出力を行うためのものです。

Djangoで一気通貫で作成した際にforms.pyを使いましたが、APIではserializers.pyでmodels.pyで定義したデータモデルとviews.pyで定義するviewsetというものを使ってAPI連携を実現します。

概念を理解してしまうと、むしろDjangoでフルで構築するよりもシンプルに感じられると思います。

3.API Endpointを作成する

(1) 仮想環境構築

では初めに、仮想環境を構築します。 Pythonのインストールが未済の場合は、まずPythonをインストールしてから行ってください。分からない方は過去記事を参照ください。

※ブラウザ上で実行できるものでなく、実際にPCにPythonをインストールする方法で行います。環境構築の記事にも書きましたが、Anacondaを入れる場合は事前にそのやり方がベストか少し考えた方がいいです。

(2) DjangoとDjango REST frameworkのインストール

pip installを使ってターミナルやコマンドプロンプト等で仮想環境を有効にした上でインストールを行います。

コマンドは以下の通りです。

corsheadersはReactからAPIを叩けるようにするために、必要なものです。

pip install django
pip install djangorestframework
pip install django-cors-headers

(3) Djangoプロジェクト・アプリケーション作成

以下のコマンドでDjangoプロジェクトを作成します。今回はREST frameworkを利用するので、drf_shopping_listというプロジェクト名にします。

django-admin startproject drf_shopping_list

次にmanage.pyファイルが存在する階層で、以下コマンドでアプリケーションを作成します。

python manage.py startapp listapp

(4) settings.py

まずはsetiings.pyファイルにアプリケーションの登録などを行います。

INSTALLED_APPSに作成したアプリケーションのlistappと、rest_frameworkと、corsheadersを追記します。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'listapp',
    'rest_framework',
    'corsheaders',
]

MIDDLEWAREにもcorsheadersのために追記して、ホワイトリストを登録します。

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',
]

CORS_ORIGIN_WHITELIST = [
    'http://localhost:3000',
]

ホワイトリストのURLですが、Reactをローカルサーバー上で実行する際、3000番のポートで実行されますので、そのように登録しています。

React実行時のターミナル

最後に、言語コードとタイムゾーンを修正します。

# Internationalization
# https://docs.djangoproject.com/en/4.0/topics/i18n/

LANGUAGE_CODE = 'ja'

TIME_ZONE = 'Asia/Tokyo'

USE_I18N = True

USE_TZ = True

これでsettings.pyは完了です。

(5) models.py

次にデータモデルを定義します。

なお、基本的には前回Djangoで実装した時と同じなのですが、データ削除や更新の際データベース上のキー項目となるidで指定をする際に項目として明示する必要があるので、項目にidを追加してます。

データベース上、キー項目は必要なので指定せずともidは勝手に生成されるのですが、APIで渡すデータに含めたいので追加してます。

models.py

from django.db import models

# Create your models here.
class Needtobuy(models.Model):
    id = models.AutoField(primary_key=True)
    article = models.CharField(max_length=50)
    register_at = models.DateField()

    def __str__(self):
        return self.article

class Alreadybuy(models.Model):
    id = models.AutoField(primary_key=True)
    article = models.CharField(max_length=50)
    register_at = models.DateField()

    def __str__(self):
        return self.article

(6) データベースのマイグレーション

データモデルの定義が終わった時点で、マイグレーションをしましょう。
以下2つのコマンドをターミナルやコマンドプロンプト等で実行ください。

python manage.py makemigrations
ptython manage.py migrate

これでデータ項目の定義は終了です。

(7) serializers.py

仕組みのところで触れたserializers.pyを作成します。
アプリケーションフォルダにserializers.pyという空ファイルを作成し、以下のコードを記載します。

from atexit import register
from dataclasses import fields
from rest_framework import serializers
from .models import Needtobuy, Alreadybuy

class NeedtobuySerializer(serializers.ModelSerializer):
    class Meta:
        model = Needtobuy
        fields = ['id', 'article', 'register_at']

class AlreadybuySerializer(serializers.ModelSerializer):
    class Meta:
        model = Alreadybuy
        fields = ['id', 'article', 'register_at']

ざっくり解説すると、rest_frameworkのserializersをインポートし、serializersのModelSerializerを継承して、serializerを作成します。

そのシリアライザーは、models.pyのどのモデルのどの項目を利用するのか?ということを定義しています。

では今度はこのシリアライザーを利用してviews.pyファイルにviewsetを作成していきます。

(8) views.py

views.pyにおいては、model.pyで定義されたデータモデルと、serializers.pyで定められたシリアライザーをもとに、返却するためのviewsetを定義するものです。

from django.shortcuts import render
from rest_framework import viewsets
from .serializers import NeedtobuySerializer, AlreadybuySerializer
from .models import Needtobuy, Alreadybuy

# Create your views here.
class NeedtobuyViewSet(viewsets.ModelViewSet):
    queryset = Needtobuy.objects.all()
    serializer_class = NeedtobuySerializer

class AlreadybuyViewSet(viewsets.ModelViewSet):
    queryset = Alreadybuy.objects.all()
    serializer_class = AlreadybuySerializer

定義内容としてはそれぞれviewetsのModelViewSetを継承して、未購入と購入済それぞれのViewSet を定義してます。

querysetというのは、データベースから抽出したオブジェクトを配列型にしているものです。
例えば、未購入のquerysetは、データベースのNeedtobuyテーブルに存在するすべてのオブジェクトを指します。filter等を利用して条件を指定して抽出をかけることも可能です。

(9) urls.py

プロジェクト側のurls.pyについては、Djangoで構築する場合と同様、アプリ側のルーティング設定を見に行くよう、includeをインポートして誘導するようにします。

urls.py (プロジェクト側)

from django.contrib import admin
from django.urls import path
from django.conf.urls import include

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

urls.py (アプリケーション側)

from django.urls import path
from django.conf.urls import include
from rest_framework import routers
from .views import NeedtobuyViewSet, AlreadybuyViewSet

router = routers.DefaultRouter()
router.register('needtobuy', NeedtobuyViewSet)
router.register('alreadybuy', AlreadybuyViewSet)

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

ポイントとしては、DjangoのみでWebアプリケーションを構築する場合、urlpatternsの中で、ルーティングを定義しますが、今回はAPIのEndpointを作成します。

rest_frameworkのrouters.DefaultRouter()のインスタンスを作成し、registerメソッドで未購入一覧と、購入済一覧それぞれEndpointを定義しています。

4.動作確認

それでは動作確認をしてみましょう。

(1) サーバー起動

 manage.pyファイルがある階層で、以下のコマンドを実行して実行してローカルサーバーを起動します。

python manage.py runserver

(2) http://127.0.0.1:8000/にアクセス

Webブラウザのアドレス欄に上記アドレスを入力する。

404エラーとなる

404エラーが出てますが、背景グレーの部分を見ると、admin/かlistapp/じゃないんだっけ?と聞かれています。

adminは管理画面なので、URLの末尾にlistapp/を付け足してアクセスしてみてください。

Api Rootの確認

Api Rootとして、needtobuyとalreadybuyそれぞれAPIで連携するためのアドレスが記載されています。

(3) 未購入一覧と購入済一覧のエンドポイントにアクセス

それぞれ、アクセスしてみましょう。

Needtobuy

ちなみにページ下部に、あるフォームからDBへの追加を行うことが可能です。私は登録したり、消したりを繰り返していたのでこんなIDで4つ登録がある状態です。

なお、[] のリスト型内に、{} の辞書型で各オブジェクトが格納されています。APIで取得すると、この配列が連携されるわけです。

(4) 各オブジェクトへのアクセス

さらに、URLの末尾にidを加えてアクセスすると、個別データにアクセスが可能です。

個別データの画面を開くと、DELETEやPUTのボタンが表示されますが、つまりidをもとに各オブジェクトへアクセスして削除や更新が可能ということです。

needtobuyのオブジェクトにアクセス

5.まとめ

今回の目的であったAPIのエンドポイントを作成し、どのURLを指定してAPI連携すればいいかが分かりました。

次回はReactで「お買い物リスト」を、今回作成したDjango REST frameworkのAPIを利用する前提で開発し、異なる2つのシステム(アプリケーション)を繋げてみたいと思います。



この記事が気に入ったら、サポートをしてみませんか?
気軽にクリエイターの支援と、記事のオススメができます!
ノンストップ飯田
中堅サラリーマン。金融関連会社で今はシステム開発関連の仕事をしています。 ビットコイン誕生の経緯を読んで、プログラミングに興味を持ち、独学でPythonを契機に諸々浅く広く首突っ込んでます。なお、会社ではVBAで効率化ツール作ることにはまってます(殆ど趣味)