【React】【Django REST Framework】環境構築編(その2)

はじめに

WebアプリケーションをReact、データベースをPostgreSQLを採用し、その両者をつなげる役割をDjango REST Frameworkに決定しました。

前回まではDjangoの環境設定を行ったので、今回はDjango REST Frameworkの環境設定を行っていきたいと思います。

Django REST Frameworkの全体像はこんな感じになります。
ザックリと各ファイルの関係性を確認しつつ、環境構築に入ろうと思います。

環境構築がまだの方は、環境構築(その1)を参照して下さい。

Django REST Frameworkの環境構築

Django REST Frameworkのインストール

プロジェクトフォルダからコマンドプロンプトを起動し、仮想環境(venv)に切り替えます。

venv\Scripts\activate.bat

仮想環境へ切り替わったら、下記コマンドを実行します。

 pip install djangorestframework

「Successfully installed djangorestframework-3.15.1」と表示されればインストール完了です。
 ※3.15.1はバージョン番号なので、状況によって変わります。

psycopg2のインストール

PythonからPostgreSQLへ接続するためのライブラリをインストールします。
psycopg2(サイコップ)インストールコマンドは下記になります。

pip install psycopg2-binary
pip install psycopg2

「Successfully installed psycopg2-binary-2.9.9」
「Successfully installed psycopg2-2.9.9」
と表示されればインストール完了です。末尾はバージョン番号になります。

settings.pyの修正

[プロジェクト名]\setings.pyに必要な修正を行っていきます。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework', # 追加
]

データベースはPostgreSQLを使用するので、sqliteから変更します。

DATABASES = {
    'default': {
        'ENGINE'  : 'django.db.backends.postgresql',
        'NAME'    : 'postgres',
        'USER'    : 'postgres',
        'PASSWORD': 'pos',
        'HOST'    : '127.0.0.1',
        'PORT'    : '5432',
    }
}

LANGUAGE_CODEとTIME_ZONEを変更します。

LANGUAGE_CODE = 'ja'
TIME_ZONE = 'Asia/Tokyo'

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

プロジェクトフォルダにて下記コマンドを実行します。
 ※アプリケーション名「app」は任意です。
  後々、色々な箇所で使用するので「app」の名前は忘れないで下さい。

python manage.py startapp app

コマンドが成功すると、プロジェクトフォルダ配下に「app」フォルダが作成されます。
現在、下記フォルダ構成となっているはずです。

Djangoアプリケーションが作成出来たので、再度setings.pyを修正するため、app/apps.pyを開きます。

from django.apps import AppConfig


class AppConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'app'

クラス「app.apps.AppConfig」を追加します。
 ※「Djangoアプリケーション名(app) + “.” + apps.pyファイル名 + “.” + 関数名」です。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework', # 追加
    'app.apps.AppConfig', # 追加
]

末尾にDjangoアプリケーション名を追記しました。

簡単な動作確認

「app」アプリケーション配下のファイルを修正します。

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return HttpResponse("表示されていますか!?")

初期状態ではurls.pyが無い為、新規ファイル作成が必要になります。

from django.urls import path
from . import views

urlpatterns = [
    path('getData/', views.test, name='test'),
]

最後に、project/urls.pyに追記を行います。

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

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

http://localhost/sample/app/getData/にアクセスし画面に「表示されていますか!?」が表示される事を確認する。

CORSの設定

DjangoにCORSを導入する為、「django-cors-headers」をインストールするため、プロジェクトフォルダにて下記コマンドを実行します。

pip install django-cors-headers

「Successfully installed django-cors-headers-4.3.1」と表示されればインストール完了です。
 ※4.3.1はバージョン番号なので、状況によって変わります。

[プロジェクト名]\setings.pyに必要な修正を行っていきます。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework', # 追加
    'app.apps.AppConfig', # 追加
    'corsheaders' # 追加
]

MIDDLEWARE = [
    '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',
    'corsheaders.middleware.CorsMiddleware', # 追加
]

# 下記は新規追加となります
CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = [
    'http://127.0.0.1',
    'http://localhost',
]

以上でCROS設定は完了になります。

動作確認

簡単なテーブルを作成する

今回は動作確認用なので、店舗マスタを1つ作成します。
 ※他のマスタ・テーブル関連は、画面作成時に作成していきたいと思います。

カラム名日本語名フィールドオプション
rowIdレコードIDAutoFieldprimary_key = True
code店舗コードCharFieldmax_length=5, blank=False, null=False
name店舗名CharFieldmax_length=50, blank=False, null=False
start_date開始日DateFieldblank=False, null=False
end_date終了日DateFieldblank=True, null=True
reg_datetime登録日時DateTimeFieldauto_now=True
cre_datetime作成日時DateTimeFieldauto_now_add=True
master.store

では、「app/models.py」に上記テーブルを設定していきます。
インデックスは、このマスタには不要なので記載していません。
 ※別の機会で追加したいと思います。

from django.db import models

# ---------------------------------------------------------
# [1] 店舗マスタ
# [master_store]
class Store(models.Model):
    # レコードID
    rowId = models.AutoField(
        'レコードID',
        primary_key = True
    )

    # 店舗コード
    code = models.CharField(
        '店舗コード',
        max_length = 5,
        blank = False,
        null = False
    )

    # 店舗名称
    name = models.CharField(
        '店舗名称',
        max_length = 50,
        blank = False,
        null = False
    )

    # 開始日
    start_date = models.DateField(
        '開始日',
        blank = False,
        null = False
    )

    # 終了日
    end_date = models.DateField(
        '終了日',
        blank = True,
        null = True
    )

    # 登録日時
    reg_datetime = models.DateTimeField(
        '登録日時',
        auto_now = True
    )

    # 作成日時
    cre_datetime =  models.DateTimeField(
        '作成日時',
        auto_now_add = True
    )

    class Meta:
        constraints = [
            # code と start_date でユニーク制約
            models.UniqueConstraint(
                fields = ['code', 'start_date'], 
                name='store_unique'
            )
        ]
        db_table = 'master_store'
        verbose_name = verbose_name_plural = '店舗マスタ'
    
    def __str__(self):
        return self.name

    def to_dict(self):
        return model_to_dict(self)

マイグレーションを行う

先ずは、「マイグレーションファイル」を作成するため、下記コマンドを実行します。
 ※末尾の「app」は、Djangoアプリケーション作成時の名称です。

python manage.py makemigrations app

実行すると「app\migrations」フォルダの直下に「0001_initial.py」と「0002_alter_store_options.py」ファイルが作成されます。

ファイルの作成を確認したら、下記コマンドで「マイグレーションファイル」のデータをDBに反映させます。
 ※末尾の「app」は、Djangoアプリケーション作成時の名称です。

python manage.py migrate app

問題無く反映できたみたいです。。

PostgreSQLの確認

PostgreSQLの操作に関しては、↓を参照して下さい。

psqlを起動し、下記コマンドを実行します。

\d master_store

テーブルの作成を確認しました。

serializersクラスの作成

データの入出力を扱うクラス、「serializers.py」を作成します。
先ほど作成した「店舗マスタ」の登録を行います。

from rest_framework import serializers
from app.models import *

# 店舗マスタ
class StoreSerializer(serializers.ModelSerializer):
    class Meta:
        model = Store
        fields = ['code','name', 'start_date','end_date']
        read_only_fields = ('rowId',)

views.pyへの追記

ページネーションの設定

一度に取得するレコード数を設定します。
「settings.py」に下記を追加します。
 ※コンソール画面を非表示にする設定も混ざっています。

# Django Rest Framework関連設定 → 新規追加
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': ('rest_framework.renderers.JSONRenderer',),
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
    'PAGE_SIZE': 30,
}

店舗マスタへのデータ入出力を追記

店舗マスタへのデータ入出力を行うために、views.pyへの追記を行います。

from django.shortcuts import render
from django.http import HttpResponse

from rest_framework import viewsets, status
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.pagination import LimitOffsetPagination

from .models import *
from .serializers import *

def test(request):
    return HttpResponse("表示されていますか!?")


# 店舗マスタ用
class StoreAPIView(APIView, LimitOffsetPagination):
    def get(self, request):
        # モデルから全データ取得
        try:
            storeList = Store.objects.all()

            results = self.paginate_queryset(storeList, request, view=self)
            serializer = StoreSerializer(results, many=True)

            return self.get_paginated_response(serializer.data)
        except Exception as e:
            return Response(str(e), status=status.HTTP_400_BAD_REQUEST)
    
    def post(self, request):
        saved_dt = error_dt = ""
        try:
            serializer = StoreSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                saved_dt = serializer.data
            else:
                error_dt = serializer.errors
        
        except Exception as e:
            error_dt = str(e)
        
        return Response(
            {
                'saved_data': saved_dt,
                'error_data': error_dt
            },
            status=(status.HTTP_201_CREATED if error_dt != "" else status.HTTP_400_BAD_REQUEST)
        )

「GET」でデータ取得し、「POST」でデータ登録を行うようにコーディングしています。

今回の追記で、インポートするコンポーネントが増えました。
ここら辺は、追々触れていきたいと思います。

urls.pyに追記する

「app/views.py」への追記が終わったら、「app/urls.py」に呼出し用の追記を行います。

from django.urls import path
from . import views

urlpatterns = [
    path('getData/', views.test, name='test'),
    path('store/', views.StoreAPIView.as_view(), name='store'),
]

動作確認

ブラウザのURLに「http://localhost/sample/app/store」を入力し、動作確認を行います。
今までの記載内容に問題が無ければ、↓の画面が起動するはずです。

まだデータ登録を行っていないので、GETの結果はcount=0件ですね。
では、POSTMANを使用して、下記データを登録したいと思います。

{
    "code":"00001",
    "name":"テスト店舗1",
    "start_date":"2024-05-11",
    "end_date":"2100-12-31"
}

Headersには「Content-Type:application/json」を設定しています。

無事、登録が行えたようです。
再度URLを叩いて、データを取得します。

先ほど登録したデータを確認できました。
これで、データの登録と取得が一通り完了となります。

おわりに

駆け足でしたが、Django REST Frarmeworkを使用してのデータ入出力までを確認しました。
これで、環境構築は一旦終わりにしたいと思います。