LoginSignup
6
10
記事投稿キャンペーン 「2024年!初アウトプットをしよう」

React + Django + CORSを使ったフロントエンド / バックエンドのデータ連携

Last updated at Posted at 2024-01-07

概要

現在再開している個人開発プロジェクトの一環で、以前実装した環境を一新して再構築しています。
その中で企業レベルのアプリ開発でも使われる機会が多そうな技術スタックを採用し取り入れているので、備忘も兼ねて投稿します。
JSONをデータ連携の手法として使うことを想定し、バックエンドで定義したデータ構成、生成データをフロントエンドで受け取り表示させる流れとしました。

実装機能

  • Reactを使ったデータ表示
  • DjangoでのModel構築 こちらの記事に移動しました
  • CORSを使ったフロントエンド / バックエンドのデータ連携
項番 記事
1 React + Django + CORSを使ったフロントエンド / バックエンドのデータ連携(本記事)
2 Django 管理画面のカスタマイズ
3 Django REST framework(DRF)を使ったAPIサーバーとReactとのデータ連携
4 Django REST frameworkのserializersを使った外部キーモデルの参照
5 React + Redux / Redux Toolkitを使った非同期通信の検証
6 APIをテストツール「Postman」を使ったDjangoとのCRUD機能実装(設計編)
7 APIをテストツール「Postman」を使ったDjangoとのCRUD機能実装(実装編)

参考文献

  • React Routerを使ったルーティング

  • CORSでのデータ連携

  • VS Code 拡張機能: Ascii Tree Generator
    • 実装必須ではありませんが、フォルダツリーの書き出しに役立ったのでメモ書き

フォルダ構成

今回使用しているものをメインに抜粋

  • フロントエンド(React / JavaScript)
[Reactプロジェクト]
├── src
    ├── App.css
    ├── App.js
    ├── App.test.js
    ├── BaseApp.css
    ├── BaseApp.js
    ├── index.css
    ├── index.js
    ├── logo.svg
    ├── reportWebVitals.js
    └── setupTests.js
├── .gitignore
├── package-lock.json
├── package.json
└── Readme.md
  • バックエンド(Python / Django)
[Djangoプロジェクト]
├── [Djangoプロジェクト_meta]
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── [Djangoアプリ]
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── db.sqlite3
└── manage.py

実装方法

フロントエンド

React公式サイトでもReact フレームワークが推奨されており、Next.jsなどを使えばバックエンドも一括で実装できるのですが、今回はバックエンドの機能をDjangoに当てるため、ネイティブなReactを使って実装します。

  • Reactプロジェクト作成 + サーバーの立ち上げ。今回はデフォルトのIPを参照します。
    http://localhost:3000/
npx create-react-app my-app
cd my-app
npm start
  • 必要パッケージをインストール
npm install axios
  • index.js ではデフォルトの App.js の代わりに BaseApp.js を新規作成して読み込んでいます。
src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import BaseApp from './BaseApp';
  :

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <React.StrictMode>
    <BaseApp />
  </React.StrictMode>
);

  :
  • データ表示画面の実装
src/BaseApp.js
import React, { useState, useEffect } from "react";
import Axios from 'axios';

const BaseApp = () => {

  // JSONデータを取得する
  const [projectList, setProjectList] = useState([]);

  const fetchData = async () => {
    const response = await Axios.get("http://localhost:8000/api/data");
    console.log(response);
    setProjectList(response.data);
  }

  useEffect(() => {
    fetchData();
  }, []);

  const filteredProjectList = projectList.filter((item) => {
    return item.id <= 3;
  });
  
  return (
    <div className="app">
      :
          <div className='section-wrapper'>
              {filteredProjectList.map((item) => (
                <dl key={item.id}>
                  <dt>{item.date}</dt>
                  <dd>{item.content}</dd>
                </dl>
              ))}
            </div>
          </div>

        </div>
      </div>
    </div>
  );
}

export default BaseApp;

画面表示時に必要なのは useState , useEffect で、バックエンドのデータ構成を非同期で受信し表示させる仕組みです。
なお Axios.get で指定しているURLは後述するDjango側の設定により変動します。

バックエンド

  • 環境設計: Minicondaを使用しています
# 環境作成
conda create -n pythonenv python=3.11
 
# 作成した環境に接続
conda activate pythonenv  # 環境名を設定

バックエンド用フォルダのルートディレクトリで、Djangoプロジェクト、Djangoアプリを作成します。
今回のディレクトリは下記の構造となります。

  • backend_django: djangoプロジェクト名
  • django_app: djangoアプリ名
django-admin startproject [プロジェクト名]
cd [プロジェクト名]
python manage.py startapp [アプリ名]
  • 初回はモデルのmigrationが必要なので、ルートディレクトリで下記を実行
python manage.py makemigrations [アプリ名]
python manage.py showmigrations [アプリ名]  # migrate一覧を表示
python manage.py migrate [アプリ名]
  • Djangoサーバーの立ち上げ。今回はデフォルトのIPを参照します。
    http://localhost:8000/
python manage.py runserver

CORSを使ったフロントエンド / バックエンドのデータ連携

  • 下記パッケージをインストール
pip install django-cors-headers
  • settings.pyでCORS設定
backend_django/backend_django/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
      :
    '[Djangoアプリ名]',
    'corsheaders',  # フロントエンドとの通信を許可するために追加
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',  # フロントエンドとの通信を許可するために追加
    'django.middleware.security.SecurityMiddleware',
      :
]

# CORSによるフロントエンドとの通信を許可するために追加
CORS_ORIGIN_WHITELIST = [
    'http://localhost:3000',  # フロントエンド側のIP
]

  • project/urls.py でアプリごとのURL定義を追加
backend_django/backend_django/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path("api/", include("django_app.urls")),
]
  • app/urls.py を新規作成
backend_django/django_app/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path("data/", views.data, name="data"),
]
  • app/views.py でデータの中身を定義
    • data の部分がJSONの仮想データになります。
backend_django/django_app/views.py
from django.shortcuts import render
from django.http import JsonResponse

def data(request):
  data = [
    {
      "id": 1,
      "date": "2022-10-01",
      "content": "【テスト】[プロジェクト]「プロジェクト名1」デプロイされました。"
    },
    {
      "id": 2,
      "date": "2022-10-02",
      "content": "[プロジェクト]「プロジェクト名2」デプロイされました。"
    },
    {
      "id": 3,
      "date": "2022-10-03",
      "content": "[プロジェクト]「プロジェクト名3」デプロイされました。"
    },
    {
      "id": 4,
      "date": "2022-10-04",
      "content": "[プロジェクト]「プロジェクト名4」デプロイされました。"
    },
      :
  ]

  return JsonResponse(data, safe=False)

ここまで設定することで、pythonアプリのURL
http://localhost:8000/api/data
が構築できるようになります。

実装ビュー・まとめ

スクリーンショット 2024-01-10 13.44.10.png

CORSを使ってデータ連携させるためには、最低限バックエンド側でのパッケージ追加・設定をしておけば実装できることがわかりました。
今回はフロント・バックともlocalhostを使っているため双方のローカルサーバーを立ち上げておく必要がありますが、実際の現場ではVPNやクラウドサーバーに代替して設定すると言うイメージでしょうか。
最終的な構成としては、以下のような形になります。

  • バックエンド
    • settings.py でCORS設定
    • app/views.py で出力(+定義)したJSONデータをフロントで参照
    • project/urls.py, app/urls.py で参照用URLを定義
  • フロントエンド
    • Axiosでバックエンド側URLをデータフェッチ
    • 取得データをフィルタリング、 map でループ表示
6
10
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
6
10