👋

axiosでDjangoとReactと連結してみた

2024/08/09に公開

元美容師のDjangoポートフォリオリニューアル日記Part.3:フロントエンド連携編

はじめに

こんにちは、やぎです!前回の記事では、Djangoでサロンの登録とリストを取り出すシンプルなAPIを作成しました。
今回は、ついにフロントエンドを担うReactも始動してバックエンドとの連結をしてみます!

今まではDjango、Reactそれぞれ単体で完結するアプリしか作成したことがなかったので楽しみです!

それではまずはバックエンド側から始めていきましょう。

バックエンドの更新

Salonモデルの拡張

まず、Salonモデルに新しいフィールドを追加しました。

前回の記事で登録したサロン名、住所、紹介文に加えて新しく追加したフィールドは以下の4つです。

phone_number(電話番号)
email(メールアドレス)
created_at(サロンデータ登録時間)
updated_at(サロンデータ更新時間)

models.pyに以下のコードを追加します

from django.db import models

class Salon(models.Model):
    name = models.CharField(max_length=100)
    address = models.CharField(max_length=200)
    description = models.TextField()
    phone_number = models.CharField(max_length=20, blank=True) #電話番号フィールドを追加
    email = models.EmailField(blank=True) #メールアドレスフィールドを追加
    created_at = models.DateTimeField(auto_now_add=True) #登録日時フィールドを追加
    updated_at = models.DateTimeField(auto_now=True) #更新日時フィールドを追加

    def __str__(self):
        return self.name

これでサロンの連絡先や登録・更新日時を管理できるようになりました!!

今回はフロントとの連結を優先するので、他のモデルの追加は次回実施します。

シリアライザーの更新

続いて、モデルの変更に合わせて、シリアライザーも更新しましょう!

serialisers.pyに先程追加したフィールド名を追加します。

rest_framework import serializers
from .models import Salon

class SalonSerializer(serializers.ModelSerializer):
    class Meta:
        model = Salon
        fields = ['id', 'name', 'address', 'description', 'phone_number', 'email', 'created_at', 'updated_at'] #'phone_number', 'email', 'created_at', 'updated_at'を追加

これで新しく追加したフィールドもAPIを通じてやり取りできるようになりました!

マイグレーションの実行

モデルの変更をしたので、データベースに反映させるためマイグレーションを実行します!

python manage.py makemigrations
python manage.py migrate

これでデータベース構造の更新が出来ました!

フロントエンドと連携するための設定

CORSの設定

フロントエンド(React)からバックエンド(Django)のAPIにアクセスするため、CORSの設定をします!
django-cors-headersをインストールするためターミナルに以下のコマンドをにゅうりょくします。

pip install django-cors-headers

settings.pyに以下のコードを追加してCORSを使えるようにしましょう

INSTALLED_APPS = [
    ...
    'corsheaders',
    ...
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',
    ...
]

CORS_ALLOW_ALL_ORIGINS = True

これでフロントとバックで連携を取るための設定が完了しました!

Reactプロジェクトを作成

さあ、いよいよReactプロジェクトの作成をします!
今回はとりあえずDjangoのAPIで登録したサロン一覧をReactでブラウザに表示出来るようにしてみましょう!

まずはすでに作成してあるfrontendディレクトリに移動してreactのインストールを実行します。
※僕の場合、frontendディレクトリ内にdockerのファイルを作成してしまっていたのでエラーがでました。以下のコマンドでReactをインストールする際はディレクトリが空である必要があるので、一旦dockerファイルを他の場所に退避させてもう一度インストールを実行することで無事にインストールすることができました。退避させたdockerファイルは再びfrontendディレクトリに戻します。

cd frontend
npx create-react-app

続いてaxiosをインストールします。
これはバックエンドのAPIと連携するためのライブラリです。

npm install axios

これでフロント側でのReactのインストール、APIと連携させるための設定は完了です!

Reactでサロン一覧を表示する

それではReactの実装をしていきます!
と言いたいところですが、その前にReactの機能であるHooksについてほんの少しだけ説明をします。

React Hooks

ReactのHooksという機能を使います。Reactには様々なフックがありますが今回はuseStateとuseEffectを使用します。

正直フックのことを完璧には理解していませんし、学習し始めた当初はちんぷんかんぷんでした。しかし使っていると少しずつ理解出るようになります。

それぞれのフックについて簡単に説明します
useStateは指定した値の状態を管理します。
一言で説明するのは難しいので簡単な例を書きます。

function Count() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>カウント数を表示: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        カウントを1増やす
      </button>
    </div>
  );
}

上記のコードではuseStateはcountの状態を管理しています。
useState(0)の0はcountの初回値を指定しています。
setCountが使用されると、useStateがcountの値を更新します。
説明が難しいですがこんな感じです笑

useEffectも説明が難しいですが、簡単に説明すると外部からなデータを反映させることができます。今回の場合はDjangoのAPIからサロン一覧を取得しています。

Hooksの他にもReactにはコンポーネント指向という考え方やSPA(シングルページアプリケーション)を作れたり便利な手法が沢山ありますが今回は使わないので、また使用する際に説明します。

Reactのコードを書く

ではいよいよコードを書いていきます!

今回はシンプルに登録したらサロン一覧をDjangoのAPI(http://localhost:8000/api/salons/)と連携して表示してみようと思います!

frontend/src/App.jsに以下のコードを書きます

import React, { useState, useEffect } from 'react';
import axios from 'axios';

function App() {
  const[salons,setSalons] = useState([]);

  useEffect(() => {
    axios.get('http://localhost:8000/api/salons/')
      .then(response => {
        setSalons(response.data);
      })
      .catch(error => {
        console.error("エラー発生", error);
      });
  },[]);

  return(
    <div>
      <h2>サロン一覧</h2>
      {salons.length === 0 ?(
        <p>サロンは登録されていません</p>
      ) : (
        <ul>
          {salons.map(salon => (
            <li key={salon.id}>
              <p>サロン名:{salon.name}</p>
              <p>住所:{salon.address}</p>
              <p>電話番号:{salon.phone_number}</p>
              <p>メールアドレス:{salon.email}</p>
              <p>紹介文:{salon.description}</p>
              
            </li>
          ))}
        </ul>
      )}
    </div>
  );

}

export default App;

最初に説明したuseStateでsalonsの状態を管理し、useEffectの中でaxiosでAPIに接続しています。さらにuseEffectの中にsetSalonsを使用して取り出したサロンデータをsalonsにセットしています。

return以降では、salonsにセットしたデータをmap関数で繰り返すことで、全てのサロンの情報を順番に取り出し表示しています。
salons.length === 0 ? はサロンの数が0だったら、つまりサロンが登録されていなければ「サロンは登録されていません」と表示します。

またcatchでエラーが出た場合はコンソールに「エラー発生」と表示するようにしています。

これでサロン一覧を表示する準備はできました!

サーバーを起動して動作確認!

ではローカルサーバーを起動して表示を確認してみましょう!
まずは以下のコマンドでフロントのサーバーを起動してみましょう!

npm start

ターミナルに表示されるURLをブラウザに入力します

無事に表示がされました!!!!!!!
まだバックエンドのサーバーを起動していないのでサロン一覧は表示されず、サロンは登録されていないと表示されますね。
ひとまず一安心です。

新しいターミナルウィンドウを開き以下のコマンドを入力しバックエンドサーバーを起動します。

python manage.py runserver

まだReactでサロン登録をする画面を作成していないので、今回はpostmanでAPIをリクエストします。
前回の記事で作成したサロン登録するためのAPIを使います。

リクエスト内容が前回のままなので、今回作成したフィールドを追加してリクエストを実行します。

postman側では無事にリクエストが完了してサロンが登録されたようです!
フロント側のブラウザをみてみましょう、、、


よし!!!!!
無事に登録したらサロンと前回までに登録していたサロン一覧、そして各サロンのフィールド情報が表示されました!!!

いやー、本当に嬉しいですね!!!!
今回はここまでとします。

最後に

今回の実装で、DjangoとReactを連携させ、サロンデータの取得と表示ができるようになりました。
簡単な機能ですがフルスタック開発の醍醐味を味わえた気がしますw

今のままではサロン一覧を表示するだけですので今後の実装でさらに機能を追加していきます!

次回の記事では以下の内容で実装予定です!

  • フロントエンドからからサロンの登録を行えるようにする。
  • モーダルでフォームを表示する

お楽しみに!

やぎ

Discussion