Djangoで顧客情報を管理し、Ubuntu18.04でReactするための最新のWebアプリケーションを構築する方法

提供:Dev Guides
移動先:案内検索

著者は、 Write for DOnations プログラムの一環として、 Open Sourcing Mental IllnessLtdを選択して寄付を受け取りました。

序章

人々はさまざまな種類のデバイスを使用してインターネットに接続し、Webを閲覧します。 このため、アプリケーションはさまざまな場所からアクセスできる必要があります。 従来のWebサイトの場合、通常は応答性の高いUIで十分ですが、より複雑なアプリケーションでは、他の手法やアーキテクチャを使用する必要があります。 これには、クライアント側のWebアプリケーション、プログレッシブWebアプリ(PWA)、またはネイティブモバイルアプリとして実装できる個別のRESTバックエンドアプリケーションとフロントエンドアプリケーションが含まれます。

より複雑なアプリケーションを構築するときに使用できるツールには、次のものがあります。

  • React 、開発者がRESTAPIバックエンド用のWebおよびネイティブフロントエンドを構築できるようにするJavaScriptフレームワーク。
  • Django は、 model view controller(MVC)ソフトウェアアーキテクチャパターンに従った、無料のオープンソースPythonWebフレームワークです。
  • Django RESTフレームワーク、DjangoでRESTAPIを構築するための強力で柔軟なツールキット。

このチュートリアルでは、React、Django、およびDjango RESTフレームワークを使用して、個別のRESTAPIバックエンドとフロントエンドを備えた最新のWebアプリケーションを構築します。 React with Djangoを使用することで、JavaScriptとフロントエンド開発の最新の進歩から利益を得ることができます。 組み込みのテンプレートエンジンを使用するDjangoアプリケーションを構築する代わりに、ReactをUIライブラリとして使用し、仮想ドキュメントオブジェクトモデル(DOM)、宣言型アプローチ、およびデータの変更をすばやくレンダリングするコンポーネントを利用します。

作成するWebアプリケーションは、顧客に関するレコードをデータベースに保存し、CRMアプリケーションの開始点として使用できます。 終了すると、 Bootstrap 4 でスタイル設定されたReactインターフェースを使用して、レコードを作成、読み取り、更新、および削除できるようになります。

前提条件

このチュートリアルを完了するには、次のものが必要です。

  • Ubuntu18.04を搭載した開発マシン。
  • Python3のインストール方法とUbuntu18.04でのローカルプログラミング環境のセットアップ方法の手順1と2に従って、Python 3、pip、およびvenvをマシンにインストールします。
  • Node.js6以降およびnpm5.2以降がマシンにインストールされている。 PPAからインストールする場合は、 Ubuntu18.04にNode.jsをインストールする方法の手順に従って両方をインストールできます。

ステップ1—Python仮想環境の作成と依存関係のインストール

このステップでは、仮想環境を作成し、Django、Django RESTフレームワーク、django-cors-headersなどのアプリケーションに必要な依存関係をインストールします。

このアプリケーションでは、DjangoとReactに2つの異なる開発サーバーを使用します。 これらは異なるポートで実行され、2つの別個のドメインとして機能します。 このため、クロスオリジンリソースシェアリング(CORS)を有効にして、ブラウザーによってブロックされることなくReactからDjangoにHTTPリクエストを送信する必要があります。

ホームディレクトリに移動し、venvPython3モジュールを使用して仮想環境を作成します。

cd ~
python3 -m venv ./env

sourceを使用して、作成した仮想環境をアクティブ化します。

source env/bin/activate

次に、pipを使用してプロジェクトの依存関係をインストールします。 これらには以下が含まれます:

  • Django :プロジェクトのWebフレームワーク。
  • Django RESTフレームワーク:Djangoを使用してRESTAPIを構築するサードパーティアプリケーション。
  • django-cors-headers :CORSを有効にするパッケージ。

Djangoフレームワークをインストールします。

pip install django djangorestframework django-cors-headers

プロジェクトの依存関係をインストールすると、DjangoプロジェクトとReactフロントエンドを作成できます。

ステップ2—Djangoプロジェクトを作成する

このステップでは、次のコマンドとユーティリティを使用してDjangoプロジェクトを生成します。

  • django-admin startproject project-namedjango-admin は、Djangoでタスクを実行するために使用されるコマンドラインユーティリティです。 startprojectコマンドは、新しいDjangoプロジェクトを作成します。
  • python manage.py startapp myappmanage.pyは、各Djangoプロジェクトに自動的に追加されるユーティリティスクリプトであり、新しいアプリケーションの作成、データベースの移行、サービスの提供など、さまざまな管理タスクを実行します。 Djangoプロジェクトをローカルで。 そのstartappコマンドは、Djangoプロジェクト内にDjangoアプリケーションを作成します。 Djangoでは、 application という用語は、プロジェクトにいくつかの機能セットを提供するPythonパッケージを表します。

まず、django-admin startprojectを使用してDjangoプロジェクトを作成します。 プロジェクトをdjangoreactprojectと呼びます。

django-admin startproject djangoreactproject 

先に進む前に、treeコマンドを使用してDjangoプロジェクトのディレクトリ構造を見てみましょう。

ヒント: tree is a useful command for viewing file and directory structures from the command line. You can install it with the following command:

sudo apt-get install tree

使用するには、目的のディレクトリにcdと入力し、treeと入力するか、tree /home/sammy/sammys-projectを使用して開始点へのパスを指定します。


プロジェクトルート内のdjangoreactprojectフォルダーに移動し、treeコマンドを実行します。

cd ~/djangoreactproject
tree

次の出力が表示されます。

Output├── djangoreactproject
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py

~/djangoreactprojectフォルダーはプロジェクトのルートです。 このフォルダ内には、作業に重要ないくつかのファイルがあります。

  • manage.py :いくつかの管理タスクを実行するユーティリティスクリプト。
  • settings.py :プロジェクトの設定を変更できるDjangoプロジェクトのメイン構成ファイル。 これらの設定には、INSTALLED_APPS、プロジェクトで有効なアプリケーションを指定する文字列のリストなどの変数が含まれます。 Djangoのドキュメントには、使用可能な設定に関する詳細情報があります。
  • urls.py :このファイルには、URLパターンと関連するビューのリストが含まれています。 各パターンは、URLとそのURLに対して呼び出される関数との間の接続をマップします。 URLとビューの詳細については、Djangoビューの作成方法のチュートリアルを参照してください。

プロジェクトを操作する最初のステップは、前のステップでインストールしたパッケージ(DjangoRESTフレームワークやDjangoCORSパッケージなど)をsettings.pyに追加して構成することです。 nanoまたはお気に入りのエディターでファイルを開きます。

nano ~/djangoreactproject/djangoreactproject/settings.py

INSTALLED_APPS設定に移動し、rest_frameworkおよびcorsheadersアプリケーションをリストの一番下に追加します。

〜/ djangoreactproject / djangoreactproject / settings.py

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

次に、以前にインストールしたCORSパッケージのcorsheaders.middleware.CorsMiddlewareミドルウェアをMIDDLEWARE設定に追加します。 この設定は、ミドルウェアのリストです。これは、Webアプリケーションが要求または応答を処理するたびに処理されるコードを含むPythonクラスです。

〜/ djangoreactproject / djangoreactproject / settings.py

...

MIDDLEWARE = [
...
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware'
]

次に、CORSを有効にできます。 CORS_ORIGIN_ALLOW_ALL設定は、すべてのドメインにCORSを許可するかどうかを指定します。CORS_ORIGIN_WHITELISTは、許可されたURLを含むPythonタプルです。 この場合、React開発サーバーはhttp://localhost:3000で実行されるため、新しいCORS_ORIGIN_ALLOW_ALL = FalseおよびCORS_ORIGIN_WHITELIST('localhost:3000',)設定をsettings.pyファイルに追加します。 次の設定をファイルの任意の場所に追加します。

〜/ djangoreactproject / djangoreactproject / settings.py

...
CORS_ORIGIN_ALLOW_ALL = False

CORS_ORIGIN_WHITELIST = (
       'localhost:3000',
)
...

その他の構成オプションは、 django-cors-headersdocsにあります。

ファイルを保存し、終了したらエディターを終了します。

まだ~/djangoreactprojectディレクトリに、customersという新しいDjangoアプリケーションを作成します。

python manage.py startapp customers

これには、顧客を管理するためのモデルおよびビューが含まれます。 モデルはアプリケーションデータのフィールドと動作を定義し、ビューはアプリケーションがWebリクエストを適切に処理し、必要な応答を返すことを可能にします。

次に、このアプリケーションをプロジェクトのsettings.pyファイルにインストールされているアプリケーションのリストに追加して、Djangoがプロジェクトの一部として認識できるようにします。 settings.pyをもう一度開きます。

nano ~/djangoreactproject/djangoreactproject/settings.py

customersアプリケーションを追加します。

〜/ djangoreactproject / djangoreactproject / settings.py

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

次に、データベースを移行して、ローカル開発サーバーを起動します。 Migrations は、モデルに加えた変更をデータベーススキーマに伝達するDjangoの方法です。 これらの変更には、たとえば、フィールドの追加やモデルの削除などが含まれます。 モデルと移行の詳細については、Djangoモデルの作成方法を参照してください。

データベースを移行します。

python manage.py migrate

ローカル開発サーバーを起動します。

python manage.py runserver

次のような出力が表示されます。

OutputPerforming system checks...

System check identified no issues (0 silenced).
October 22, 2018 - 15:14:50
Django version 2.1.2, using settings 'djangoreactproject.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Webアプリケーションはhttp://127.0.0.1:8000から実行されます。 Webブラウザでこのアドレスに移動すると、次のページが表示されます。

この時点で、アプリケーションを実行したままにし、新しいターミナルを開いてプロジェクトの開発を続行します。

ステップ3—Reactフロントエンドを作成する

このセクションでは、Reactを使用してプロジェクトのフロントエンドアプリケーションを作成します。

Reactには、Webpackを直接構成しなくてもReactプロジェクトをすばやく生成できる公式ユーティリティがあります。 Webpackは、JavaScriptコード、CSS、画像などのWebアセットをバンドルするために使用されるモジュールバンドラーです。 通常、Webpackを使用する前に、さまざまな構成オプションを設定する必要がありますが、create-react-appユーティリティのおかげで、より詳細な制御が必要であると判断するまで、Webpackを直接処理する必要はありません。 create-react-appを実行するには、npmパッケージバイナリを実行するツールであるnpxを使用できます。

2番目のターミナルで、プロジェクトディレクトリにいることを確認します。

cd ~/djangoreactproject

create-react-appnpxを使用して、frontendというReactプロジェクトを作成します。

npx create-react-app frontend

次に、Reactアプリケーション内をナビゲートし、開発サーバーを起動します。

cd ~/djangoreactproject/frontend
npm start

アプリケーションはhttp://localhost:3000/から実行されます。

React開発サーバーを実行したままにし、別のターミナルウィンドウを開いて続行します。

この時点でプロジェクト全体のディレクトリ構造を確認するには、ルートフォルダに移動して、treeを再度実行します。

cd ~/djangoreactproject
tree

次のような構造が表示されます。

Output├── customers
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── djangoreactproject
│   ├── __init__.py
│   ├── __pycache__
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── frontend
│   ├── package.json
│   ├── public
│   │   ├── favicon.ico
│   │   ├── index.html
│   │   └── manifest.json
│   ├── README.md
│   ├── src
│   │   ├── App.css
│   │   ├── App.js
│   │   ├── App.test.js
│   │   ├── index.css
│   │   ├── index.js
│   │   ├── logo.svg
│   │   └── registerServiceWorker.js
│   └── yarn.lock
└── manage.py

このアプリケーションはBootstrap4を使用してReactインターフェースのスタイルを設定するため、CSS設定を管理するfrontend/src/App.cssファイルにそれを含めます。 ファイルを開きます。

nano ~/djangoreactproject/frontend/src/App.css

次のimportをファイルの先頭に追加します。 ファイルの既存のコンテンツを削除できますが、必須ではありません。

〜/ djangoreactproject / frontend / src / App.css

@import  'https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css';

ここで、@importは、他のスタイルシートからスタイルルールをインポートするために使用されるCSS命令です。

バックエンドアプリケーションとフロントエンドアプリケーションの両方を作成したので、Customerモデルといくつかのデモデータを作成しましょう。

ステップ4—顧客モデルと初期データの作成

DjangoアプリケーションとReactフロントエンドを作成したら、次のステップは、顧客に関する情報を保持するデータベーステーブルを表すCustomerモデルを作成することです。 Django Object Relational Mapper(ORM)は、Pythonクラスと変数をSQLテーブルと列にマッピングすることでデータベース操作を処理するため、SQLは必要ありません。 このようにして、Django ORMは、Pythonインターフェースを介してデータベースとのSQLの相互作用を抽象化します。

仮想環境を再度アクティブ化します。

cd ~
source env/bin/activate

customersディレクトリに移動し、アプリケーションのモデルを保持するPythonファイルであるmodels.pyを開きます。

cd ~/djangoreactproject/customers/
nano models.py

このファイルには、次の内容が含まれます。

〜/ djangoreactproject / customers / models.py

from django.db import models
# Create your models here.

from django.db import models importステートメントのおかげで、CustomerモデルのAPIはすでにファイルにインポートされています。 次に、models.Modelを拡張するCustomerクラスを追加します。 Djangoの各モデルは、django.db.models.Modelを拡張するPythonクラスです。

Customerモデルには、次のデータベースフィールドがあります。

  • first_name —顧客の名。
  • last_name —顧客の姓。
  • email —顧客の電子メールアドレス。
  • phone —顧客の電話番号。
  • address —顧客の住所。
  • description —顧客の説明。
  • createdAt —顧客が追加された日付。

また、モデルの表示方法を定義する__str__()関数を追加します。 私たちの場合、それは顧客の名になります。 クラスの構築とオブジェクトの定義の詳細については、 Python3でクラスを構築してオブジェクトを定義する方法を参照してください。

次のコードをファイルに追加します。

〜/ djangoreactproject / customers / models.py

from django.db import models

class Customer(models.Model):
    first_name = models.CharField("First name", max_length=255)
    last_name = models.CharField("Last name", max_length=255)
    email = models.EmailField()
    phone = models.CharField(max_length=20)
    address =  models.TextField(blank=True, null=True)
    description = models.TextField(blank=True, null=True)
    createdAt = models.DateTimeField("Created At", auto_now_add=True)
    
    def __str__(self):
        return self.first_name

次に、データベースを移行してデータベーステーブルを作成します。 makemigrations コマンドは、モデルの変更が追加される移行ファイルを作成し、migrateは移行ファイルの変更をデータベースに適用します。

プロジェクトのルートフォルダに戻ります。

cd ~/djangoreactproject

以下を実行して、移行ファイルを作成します。

python manage.py makemigrations

次のような出力が得られます。

Outputcustomers/migrations/0001_initial.py
    - Create model Customer

これらの変更をデータベースに適用します。

python manage.py migrate

移行が成功したことを示す出力が表示されます。

OutputOperations to perform:
  Apply all migrations: admin, auth, contenttypes, customers, sessions
Running migrations:
  Applying customers.0001_initial... OK

次に、データ移行ファイルを使用して初期顧客データを作成します。 データ移行ファイルは、データベース内のデータを追加または変更する移行です。 customersアプリケーション用の空のデータ移行ファイルを作成します。

python manage.py makemigrations --empty --name customers customers

移行ファイルの名前とともに、次の確認が表示されます。

OutputMigrations for 'customers':
  customers/migrations/0002_customers.py

移行ファイルの名前は0002_customers.pyであることに注意してください。

次に、customersアプリケーションの移行フォルダー内に移動します。

cd ~/djangoreactproject/customers/migrations

作成した移行ファイルを開きます。

nano 0002_customers.py

これはファイルの最初の内容です:

〜/ djangoreactproject / customers / migrations / 0002_customers.py

from django.db import migrations

class Migration(migrations.Migration):
    dependencies = [
        ('customers', '0001_initial'),
    ]
    operations = [
    ]        

importステートメントは、データベースを操作するためのクラスを含む組み込みパッケージであるdjango.dbから、移行を作成するためのDjangoAPIであるmigrationsAPIをインポートします。

Migrationクラスは、データベースの移行時に実行される操作を記述するPythonクラスです。 このクラスはmigrations.Migrationを拡張し、2つのリストがあります。

  • 依存関係:依存する移行が含まれます。
  • operations :移行を適用するときに実行される操作が含まれます。

次に、 method を追加して、デモの顧客データを作成します。 Migrationクラスの定義の前に次のメソッドを追加します。

〜/ djangoreactproject / customers / migrations / 0002_customers.py

...
def create_data(apps, schema_editor):
    Customer = apps.get_model('customers', 'Customer')
    Customer(first_name="Customer 001", last_name="Customer 001", email="[email protected]", phone="00000000", address="Customer 000 Address", description= "Customer 001 description").save()

...

このメソッドでは、customersアプリのCustomerクラスを取得し、データベースに挿入するデモ顧客を作成します。

新しい顧客の作成を可能にするCustomerクラスを取得するには、appsオブジェクトのget_model()メソッドを使用します。 appsオブジェクトは、インストールされているアプリケーションとそのデータベースモデルのレジストリを表します。

appsオブジェクトは、create_data()を実行するために使用すると、RunPython()メソッドから渡されます。 migrations.RunPython()メソッドを空のoperationsリストに追加します。

〜/ djangoreactproject / customers / migrations / 0002_customers.py

...
    operations = [
        migrations.RunPython(create_data),
    ]  

RunPython()は、移行でカスタムPythonコードを実行できるようにするMigrationsAPIの一部です。 operationsリストは、移行を適用するときにこのメソッドが実行されることを指定しています。

これは完全なファイルです:

〜/ djangoreactproject / customers / migrations / 0002_customers.py

from django.db import migrations

def create_data(apps, schema_editor):
    Customer = apps.get_model('customers', 'Customer')
    Customer(first_name="Customer 001", last_name="Customer 001", email="[email protected]", phone="00000000", address="Customer 000 Address", description= "Customer 001 description").save()

class Migration(migrations.Migration):
    dependencies = [
        ('customers', '0001_initial'),
    ]
    operations = [
        migrations.RunPython(create_data),
    ]        

データ移行の詳細については、Djangoでのデータ移行に関するドキュメントを参照してください。

データベースを移行するには、最初にプロジェクトのルートフォルダーに戻ります。

cd ~/djangoreactproject

データベースを移行して、デモデータを作成します。

python manage.py migrate

移行を確認する出力が表示されます。

OutputOperations to perform:
  Apply all migrations: admin, auth, contenttypes, customers, sessions
Running migrations:
  Applying customers.0002_customers... OK

このプロセスの詳細については、Djangoモデルの作成方法を参照してください。

顧客モデルとデモデータを作成したら、RESTAPIの構築に進むことができます。

ステップ5—RESTAPIを作成する

このステップでは、DjangoRESTフレームワークを使用してRESTAPIを作成します。 いくつかの異なるAPIビューを作成します。 APIビューはAPIリクエストまたは呼び出しを処理する関数であり、APIエンドポイントはRESTシステムとのタッチポイントを表す一意のURLです。 たとえば、ユーザーがGETリクエストをAPIエンドポイントに送信すると、Djangoは対応する関数またはAPIビューを呼び出してリクエストを処理し、可能な結果を返します。

シリアライザーも利用します。 Django RESTフレームワークのシリアライザーを使用すると、複雑なモデルインスタンスとQuerySetをAPIで使用するためにJSON形式に変換できます。 シリアライザークラスは他の方向にも機能し、データを解析してDjangoモデルとQuerySetに逆シリアル化するメカニズムを提供します。

APIエンドポイントには次のものが含まれます。

  • api/customers:このエンドポイントは、顧客を作成し、ページ化された顧客のセットを返すために使用されます。
  • api/customers/<pk>:このエンドポイントは、主キーまたはIDによって単一の顧客を取得、更新、および削除するために使用されます。

また、プロジェクトのurls.pyファイルに対応するエンドポイント(つまり、api/customersおよびapi/customers/<pk>)のURLを作成します。

Customerモデルのシリアライザークラスを作成することから始めましょう。

シリアライザークラスの追加

Customerモデルのシリアライザークラスを作成することは、顧客インスタンスとQuerySetをJSONとの間で変換するために必要です。 シリアライザークラスを作成するには、最初にcustomersアプリケーション内にserializers.pyファイルを作成します。

cd ~/djangoreactproject/customers/
nano serializers.py

次のコードを追加して、シリアライザーAPIとCustomerモデルをインポートします。

〜/ djangoreactproject / Customers / serializers.py

from rest_framework import serializers
from .models import Customer

次に、serializers.ModelSerializerを拡張し、シリアル化されるフィールドを指定するシリアライザークラスを作成します。

〜/ djangoreactproject / Customers / serializers.py

...
class CustomerSerializer(serializers.ModelSerializer):

    class Meta:
        model = Customer 
        fields = ('pk','first_name', 'last_name', 'email', 'phone','address','description')

Metaクラスは、シリアル化するモデルとフィールドを指定します:pkfirst_namelast_nameemailphoneaddressdescription

これはファイルの完全な内容です:

〜/ djangoreactproject / Customers / serializers.py

from rest_framework import serializers
from .models import Customer

class CustomerSerializer(serializers.ModelSerializer):

    class Meta:
        model = Customer 
        fields = ('pk','first_name', 'last_name', 'email', 'phone','address','description')

シリアライザークラスを作成したので、APIビューを追加できます。

APIビューの追加

このセクションでは、ユーザーがビュー関数に対応するエンドポイントにアクセスしたときにDjangoによって呼び出されるアプリケーションのAPIビューを作成します。

~/djangoreactproject/customers/views.pyを開きます:

nano ~/djangoreactproject/customers/views.py

そこにあるものを削除し、次のインポートを追加します。

〜/ djangoreactproject / customers / views.py

from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import Customer 
from .serializers import *

作成したシリアライザーを、CustomerモデルとDjangoおよびDjangoRESTFrameworkAPIとともにインポートしています。

次に、POSTおよびGETHTTPリクエストを処理するためのビューを追加します。

〜/ djangoreactproject / customers / views.py

...

@api_view(['GET', 'POST'])
def customers_list(request):
    """
 List  customers, or create a new customer.
 """
    if request.method == 'GET':
        data = []
        nextPage = 1
        previousPage = 1
        customers = Customer.objects.all()
        page = request.GET.get('page', 1)
        paginator = Paginator(customers, 10)
        try:
            data = paginator.page(page)
        except PageNotAnInteger:
            data = paginator.page(1)
        except EmptyPage:
            data = paginator.page(paginator.num_pages)

        serializer = CustomerSerializer(data,context={'request': request} ,many=True)
        if data.has_next():
            nextPage = data.next_page_number()
        if data.has_previous():
            previousPage = data.previous_page_number()
        
        return Response({'data': serializer.data , 'count': paginator.count, 'numpages' : paginator.num_pages, 'nextlink': '/api/customers/?page=' + str(nextPage), 'prevlink': '/api/customers/?page=' + str(previousPage)})

    elif request.method == 'POST':
        serializer = CustomerSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

まず、@api_view(['GET', 'POST'])デコレータを使用して、GETおよびPOSTリクエストを受け入れることができるAPIビューを作成します。 デコレータは、別の関数を受け取り、それを動的に拡張する関数です。

メソッド本体では、request.method変数を使用して、現在のHTTPメソッドをチェックし、リクエストタイプに応じて対応するロジックを実行します。

  • GETリクエストの場合、メソッドはDjango Paginator を使用してデータをページ分割し、シリアル化後のデータの最初のページ、利用可能な顧客の数、利用可能なページの数、および前のページへのリンクを返します。次のページ。 Paginatorは、データのリストをページにページ分けし、各ページのアイテムにアクセスするためのメソッドを提供する組み込みのDjangoクラスです。
  • POSTリクエストの場合、このメソッドは受信した顧客データをシリアル化してから、シリアライザーオブジェクトのsave()メソッドを呼び出します。 次に、201ステータスコードを持つHttpResponseのインスタンスであるResponseオブジェクトを返します。 作成する各ビューは、HttpResponseオブジェクトを再作成する責任があります。 save()メソッドは、シリアル化されたデータをデータベースに保存します。

HttpResponseとビューの詳細については、ビュー関数の作成に関するこの説明を参照してください。

次に、pk(主キー)による顧客の取得、更新、および削除のためのGET、PUT、およびDELETE要求の処理を担当するAPIビューを追加します。

〜/ djangoreactproject / customers / views.py

...
@api_view(['GET', 'PUT', 'DELETE'])
def customers_detail(request, pk):
 """
 Retrieve, update or delete a customer by id/pk.
 """
    try:
        customer = Customer.objects.get(pk=pk)
    except Customer.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = CustomerSerializer(customer,context={'request': request})
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = CustomerSerializer(customer, data=request.data,context={'request': request})
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        customer.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

このメソッドは@api_view(['GET', 'PUT', 'DELETE'])で装飾されており、GET、PUT、およびDELETEリクエストを受け入れることができるAPIビューであることを示しています。

request.methodフィールドのチェックは、要求メソッドを検証し、その値に応じて適切なロジックを呼び出します。

  • GETリクエストの場合、顧客データはシリアル化され、Responseオブジェクトを使用して送信されます。
  • PUTリクエストの場合、このメソッドは新しい顧客データのシリアライザーを作成します。 次に、作成したシリアライザオブジェクトのsave()メソッドを呼び出します。 最後に、更新された顧客とともにResponseオブジェクトを送信します。
  • DELETEリクエストの場合、メソッドはcustomerオブジェクトのdelete()メソッドを呼び出して削除し、データのないResponseオブジェクトを返します。

完成したファイルは次のようになります。

〜/ djangoreactproject / customers / views.py

from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from .models import Customer 
from .serializers import *


@api_view(['GET', 'POST'])
def customers_list(request):
    """
 List  customers, or create a new customer.
 """
    if request.method == 'GET':
        data = []
        nextPage = 1
        previousPage = 1
        customers = Customer.objects.all()
        page = request.GET.get('page', 1)
        paginator = Paginator(customers, 5)
        try:
            data = paginator.page(page)
        except PageNotAnInteger:
            data = paginator.page(1)
        except EmptyPage:
            data = paginator.page(paginator.num_pages)

        serializer = CustomerSerializer(data,context={'request': request} ,many=True)
        if data.has_next():
            nextPage = data.next_page_number()
        if data.has_previous():
            previousPage = data.previous_page_number()
        
        return Response({'data': serializer.data , 'count': paginator.count, 'numpages' : paginator.num_pages, 'nextlink': '/api/customers/?page=' + str(nextPage), 'prevlink': '/api/customers/?page=' + str(previousPage)})

    elif request.method == 'POST':
        serializer = CustomerSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@api_view(['GET', 'PUT', 'DELETE'])
def customers_detail(request, pk):
    """
 Retrieve, update or delete a customer by id/pk.
 """
    try:
        customer = Customer.objects.get(pk=pk)
    except Customer.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = CustomerSerializer(customer,context={'request': request})
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = CustomerSerializer(customer, data=request.data,context={'request': request})
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        customer.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

これで、エンドポイントの作成に進むことができます。

APIエンドポイントの追加

ここで、APIエンドポイントを作成します。顧客のクエリと作成用のapi/customers/と、pkによる単一の顧客の取得、更新、または削除用のapi/customers/<pk>です。

~/djangoreactproject/djangoreactproject/urls.pyを開きます:

nano ~/djangoreactproject/djangoreactproject/urls.py

そこにあるものを残しますが、ファイルの上部にあるcustomersビューにインポートを追加します。

〜/ djangoreactproject / djangoreactproject / urls.py

from django.contrib import admin
from django.urls import path
from customers import views
from django.conf.urls import url

次に、api/customers/およびapi/customers/<pk>のURLを、アプリケーションのURLを含むurlpatternsリストに追加します。

〜/ djangoreactproject / djangoreactproject / urls.py

...

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^api/customers/$', views.customers_list),
    url(r'^api/customers/(?P<pk>[0-9]+)$', views.customers_detail),
]

RESTエンドポイントを作成したら、それらをどのように使用できるかを見てみましょう。

ステップ6—AxiosでRESTAPIを使用する

このステップでは、API呼び出しを行うために使用するHTTPクライアントであるAxiosをインストールします。 また、作成したAPIエンドポイントを使用するクラスも作成します。

まず、仮想環境を非アクティブ化します。

deactivate

次に、frontendフォルダーに移動します。

cd ~/djangoreactproject/frontend

以下を使用して、npmからaxiosをインストールします。

npm install axios --save

--saveオプションは、axios依存関係をアプリケーションのpackage.jsonファイルに追加します。

次に、CustomersService.jsというJavaScriptファイルを作成します。このファイルには、RESTAPIを呼び出すためのコードが含まれています。 これは、srcフォルダー内に作成します。このフォルダーには、プロジェクトのアプリケーションコードがあります。

cd src
nano CustomersService.js

次のコードを追加します。このコードには、DjangoRESTAPIに接続するためのメソッドが含まれています。

〜/ djangoreactproject / frontend / src / CustomersService.js

import axios from 'axios';
const API_URL = 'http://localhost:8000';

export default class CustomersService{
    
    constructor(){}
    
    
    getCustomers() {
        const url = `${API_URL}/api/customers/`;
        return axios.get(url).then(response => response.data);
    }  
    getCustomersByURL(link){
        const url = `${API_URL}${link}`;
        return axios.get(url).then(response => response.data);
    }
    getCustomer(pk) {
        const url = `${API_URL}/api/customers/${pk}`;
        return axios.get(url).then(response => response.data);
    }
    deleteCustomer(customer){
        const url = `${API_URL}/api/customers/${customer.pk}`;
        return axios.delete(url);
    }
    createCustomer(customer){
        const url = `${API_URL}/api/customers/`;
        return axios.post(url,customer);
    }
    updateCustomer(customer){
        const url = `${API_URL}/api/customers/${customer.pk}`;
        return axios.put(url,customer);
    }
}

CustomersServiceクラスは、次のAxiosメソッドを呼び出します。

  • getCustomers():顧客の最初のページを取得します。
  • getCustomersByURL():URLで顧客を取得します。 これにより、/api/customers/?page=2などのリンクを渡すことで、顧客の次のページを取得できます。
  • getCustomer():主キーで顧客を取得します。
  • createCustomer():顧客を作成します。
  • updateCustomer():顧客を更新します。
  • deleteCustomer():顧客を削除します。

CustomersListコンポーネントを作成することで、APIからのデータをReactUIインターフェースに表示できるようになりました。

ステップ7—ReactアプリケーションでAPIからのデータを表示する

このステップでは、CustomersListReactコンポーネントを作成します。 ReactコンポーネントはUIの一部を表します。 また、UIを独立した再利用可能な部分に分割することもできます。

frontend/srcCustomersList.jsを作成することから始めます。

nano ~/djangoreactproject/frontend/src/CustomersList.js

ReactComponentをインポートして、Reactコンポーネントを作成することから始めます。

〜/ djangoreactproject / frontend / src / CustomersList.js

import  React, { Component } from  'react';

次に、前の手順で作成したCustomersServiceモジュールをインポートしてインスタンス化します。これにより、RESTAPIバックエンドとインターフェイスするメソッドが提供されます。

〜/ djangoreactproject / frontend / src / CustomersList.js

...
import  CustomersService  from  './CustomersService';

const  customersService  =  new  CustomersService();

次に、Componentを拡張してRESTAPIを呼び出すCustomersListコンポーネントを作成します。 Reactコンポーネントは、コンポーネントクラス拡張またはサブクラス化する必要があります。 E6クラスと継承の詳細については、JavaScriptでのクラスの理解に関するチュートリアルを参照してください。

次のコードを追加して、react.Componentを拡張するReactコンポーネントを作成します。

〜/ djangoreactproject / frontend / src / CustomersList.js

...
class  CustomersList  extends  Component {

    constructor(props) {
        super(props);
        this.state  = {
            customers: [],
            nextPageURL:  ''
        };
        this.nextPage  =  this.nextPage.bind(this);
        this.handleDelete  =  this.handleDelete.bind(this);
    }
}
export  default  CustomersList;

コンストラクター内で、stateオブジェクトを初期化しています。 これは、空のcustomers arrayを使用してコンポーネントの状態変数を保持します。 この配列は、顧客と、バックエンドAPIから取得する次のページのURLを保持するnextPageURLを保持します。 また、バインディング nextPage()およびhandleDelete()メソッドからthisにバインドしているため、HTMLコードからアクセスできます。

次に、componentDidMount()メソッドを追加し、CustomersListクラス内のgetCustomers()の呼び出しを、中括弧を閉じる前に追加します。

componentDidMount()メソッドは、コンポーネントが作成されてDOMに挿入されるときに呼び出されるコンポーネントのライフサイクルメソッドです。 getCustomers()は、Customers Serviceオブジェクトを呼び出して、データの最初のページと次のページのリンクをDjangoバックエンドから取得します。

〜/ djangoreactproject / frontend / src / CustomersList.js

...
componentDidMount() {
    var  self  =  this;
    customersService.getCustomers().then(function (result) {
        self.setState({ customers:  result.data, nextPageURL:  result.nextlink})
    });
}

次に、componentDidMount()の下に、顧客の削除を処理するhandleDelete()メソッドを追加します。

〜/ djangoreactproject / frontend / src / CustomersList.js

...
handleDelete(e,pk){
    var  self  =  this;
    customersService.deleteCustomer({pk :  pk}).then(()=>{
        var  newArr  =  self.state.customers.filter(function(obj) {
            return  obj.pk  !==  pk;
        });
        self.setState({customers:  newArr})
    });
}

handleDelete()メソッドは、deleteCustomer()メソッドを呼び出し、pk(主キー)を使用して顧客を削除します。 操作が成功すると、削除された顧客のcustomersアレイが除外されます。

次に、nextPage()メソッドを追加して、次のページのデータを取得し、次のページのリンクを更新します。

〜/ djangoreactproject / frontend / src / CustomersList.js

...
nextPage(){
    var  self  =  this;
    customersService.getCustomersByURL(this.state.nextPageURL).then((result) => {
        self.setState({ customers:  result.data, nextPageURL:  result.nextlink})
    });
}

nextPage()メソッドは、getCustomersByURL()メソッドを呼び出します。このメソッドは、状態オブジェクトthis.state.nextPageURLから次のページのURLを取得し、返されたデータでcustomers配列を更新します。 。

最後に、コンポーネント render()メソッドを追加します。これにより、コンポーネントの状態から顧客のテーブルがレンダリングされます。

〜/ djangoreactproject / frontend / src / CustomersList.js

...
render() {

    return (
    <div  className="customers--list">
        <table  className="table">
            <thead  key="thead">
            <tr>
                <th>#</th>
                <th>First Name</th>
                <th>Last Name</th>
                <th>Phone</th>
                <th>Email</th>
                <th>Address</th>
                <th>Description</th>
                <th>Actions</th>
            </tr>
            </thead>
            <tbody>
                {this.state.customers.map( c  =>
                <tr  key={c.pk}>
                    <td>{c.pk}  </td>
                    <td>{c.first_name}</td>
                    <td>{c.last_name}</td>
                    <td>{c.phone}</td>
                    <td>{c.email}</td>
                    <td>{c.address}</td>
                    <td>{c.description}</td>
                    <td>
                    <button  onClick={(e)=>  this.handleDelete(e,c.pk) }> Delete</button>
                    <a  href={"/customer/" + c.pk}> Update</a>
                    </td>
                </tr>)}
            </tbody>
        </table>
        <button  className="btn btn-primary"  onClick=  {  this.nextPage  }>Next</button>
    </div>
    );
}

これはファイルの完全な内容です:

〜/ djangoreactproject / frontend / src / CustomersList.js

import  React, { Component } from  'react';
import  CustomersService  from  './CustomersService';

const  customersService  =  new  CustomersService();

class  CustomersList  extends  Component {

constructor(props) {
    super(props);
    this.state  = {
        customers: [],
        nextPageURL:  ''
    };
    this.nextPage  =  this.nextPage.bind(this);
    this.handleDelete  =  this.handleDelete.bind(this);
}

componentDidMount() {
    var  self  =  this;
    customersService.getCustomers().then(function (result) {
        console.log(result);
        self.setState({ customers:  result.data, nextPageURL:  result.nextlink})
    });
}
handleDelete(e,pk){
    var  self  =  this;
    customersService.deleteCustomer({pk :  pk}).then(()=>{
        var  newArr  =  self.state.customers.filter(function(obj) {
            return  obj.pk  !==  pk;
        });
        
        self.setState({customers:  newArr})
    });
}

nextPage(){
    var  self  =  this;
    console.log(this.state.nextPageURL);       
    customersService.getCustomersByURL(this.state.nextPageURL).then((result) => {
        self.setState({ customers:  result.data, nextPageURL:  result.nextlink})
    });
}
render() {

    return (
        <div  className="customers--list">
            <table  className="table">
            <thead  key="thead">
            <tr>
                <th>#</th>
                <th>First Name</th>
                <th>Last Name</th>
                <th>Phone</th>
                <th>Email</th>
                <th>Address</th>
                <th>Description</th>
                <th>Actions</th>
            </tr>
            </thead>
            <tbody>
            {this.state.customers.map( c  =>
                <tr  key={c.pk}>
                <td>{c.pk}  </td>
                <td>{c.first_name}</td>
                <td>{c.last_name}</td>
                <td>{c.phone}</td>
                <td>{c.email}</td>
                <td>{c.address}</td>
                <td>{c.description}</td>
                <td>
                <button  onClick={(e)=>  this.handleDelete(e,c.pk) }> Delete</button>
                <a  href={"/customer/" + c.pk}> Update</a>
                </td>
            </tr>)}
            </tbody>
            </table>
            <button  className="btn btn-primary"  onClick=  {  this.nextPage  }>Next</button>
        </div>
        );
  }
}
export  default  CustomersList;

顧客のリストを表示するためのCustomersListコンポーネントを作成したので、顧客の作成と更新を処理するコンポーネントを追加できます。

ステップ8—顧客の追加Reactコンポーネントの作成と更新

このステップでは、顧客の作成と更新を処理するCustomerCreateUpdateコンポーネントを作成します。 これは、ユーザーが新しい顧客に関するデータを入力するか、既存のエントリを更新するために使用できるフォームを提供することによって行われます。

frontend/srcで、CustomerCreateUpdate.jsファイルを作成します。

nano ~/djangoreactproject/frontend/src/CustomerCreateUpdate.js

次のコードを追加して、ReactComponentをインポートしてReactコンポーネントを作成します。

〜/ djangoreactproject / frontend / src / CustomerCreateUpdate.js

import  React, { Component } from  'react';

前の手順で作成したCustomersServiceクラスをインポートしてインスタンス化することもできます。これにより、RESTAPIバックエンドとインターフェイスするメソッドが提供されます。

〜/ djangoreactproject / frontend / src / CustomerCreateUpdate.js

...
import  CustomersService  from  './CustomersService';

const  customersService  =  new  CustomersService();

次に、Componentを拡張するCustomerCreateUpdateコンポーネントを作成して、顧客を作成および更新します。

〜/ djangoreactproject / frontend / src / CustomerCreateUpdate.js

...
class  CustomerCreateUpdate  extends  Component {
    
    constructor(props) {
        super(props);
    }

}
export default CustomerCreateUpdate;

クラス定義内に、コンポーネントのrender()メソッドを追加します。これにより、顧客に関する情報を取得するHTMLフォームがレンダリングされます。

〜/ djangoreactproject / frontend / src / CustomerCreateUpdate.js

...
render() {
        return (
          <form onSubmit={this.handleSubmit}>
          <div className="form-group">
            <label>
              First Name:</label>
              <input className="form-control" type="text" ref='firstName' />
            
            <label>
              Last Name:</label>
              <input className="form-control" type="text" ref='lastName'/>
            
            <label>
              Phone:</label>
              <input className="form-control" type="text" ref='phone' />
            
            <label>
              Email:</label>
              <input className="form-control" type="text" ref='email' />
            
            <label>
              Address:</label>
              <input className="form-control" type="text" ref='address' />
            
            <label>
              Description:</label>
              <textarea className="form-control" ref='description' ></textarea>
              

            <input className="btn btn-primary" type="submit" value="Submit" />
            </div>
          </form>
        );
  }

フォーム入力要素ごとに、このメソッドはrefプロパティを追加して、フォーム要素の値にアクセスして設定します。

次に、render()メソッドの上に、handleSubmit(event)メソッドを定義して、ユーザーが送信ボタンをクリックしたときに適切な機能が得られるようにします。

〜/ djangoreactproject / frontend / src / CustomerCreateUpdate.js

...
handleSubmit(event) {
    const { match: { params } } =  this.props;
    if(params  &&  params.pk){
        this.handleUpdate(params.pk);
    }
    else
    {
        this.handleCreate();
    }
    event.preventDefault();
}

...

handleSubmit(event)メソッドはフォームの送信を処理し、ルートに応じて、handleUpdate(pk)メソッドを呼び出して、渡されたpkまたはhandleCreate()で顧客を更新します。 ]新しい顧客を作成する方法。 これらのメソッドはまもなく定義します。

コンポーネントコンストラクターに戻り、新しく追加されたhandleSubmit()メソッドをthisにバインドして、フォームからアクセスできるようにします。

〜/ djangoreactproject / frontend / src / CustomerCreateUpdate.js

...
class CustomerCreateUpdate extends Component {

constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
}
...

次に、handleCreate()メソッドを定義して、フォームデータから顧客を作成します。 handleSubmit(event)メソッドの上に、次のコードを追加します。

〜/ djangoreactproject / frontend / src / CustomerCreateUpdate.js

...
handleCreate(){
    customersService.createCustomer(
        {
        "first_name":  this.refs.firstName.value,
        "last_name":  this.refs.lastName.value,
        "email":  this.refs.email.value,
        "phone":  this.refs.phone.value,
        "address":  this.refs.address.value,
        "description":  this.refs.description.value
        }).then((result)=>{
                alert("Customer created!");
        }).catch(()=>{
                alert('There was an error! Please re-check your form.');
        });
}

...

handleCreate()メソッドは、入力されたデータから顧客を作成するために使用されます。 対応するCustomersService.createCustomer()メソッドを呼び出して、バックエンドへの実際のAPI呼び出しを行い、顧客を作成します。

次に、handleCreate()メソッドの下で、handleUpdate(pk)メソッドを定義して更新を実装します。

〜/ djangoreactproject / frontend / src / CustomerCreateUpdate.js

...
handleUpdate(pk){
customersService.updateCustomer(
    {
    "pk":  pk,
    "first_name":  this.refs.firstName.value,
    "last_name":  this.refs.lastName.value,
    "email":  this.refs.email.value,
    "phone":  this.refs.phone.value,
    "address":  this.refs.address.value,
    "description":  this.refs.description.value
    }
    ).then((result)=>{
        
        alert("Customer updated!");
    }).catch(()=>{
        alert('There was an error! Please re-check your form.');
    });
}

updateCustomer()メソッドは、顧客情報フォームからの新しい情報を使用して、pkによって顧客を更新します。 customersService.updateCustomer()メソッドを呼び出します。

次に、componentDidMount()メソッドを追加します。 ユーザーがcustomer/:pkルートにアクセスした場合、URLの主キーを使用して、顧客に関連する情報をフォームに入力します。 これを行うには、コンポーネントがcomponentDidMount()のライフサイクルイベントにマウントされた後に、getCustomer(pk)メソッドを追加できます。 このメソッドを追加するには、コンポーネントコンストラクターの下に次のコードを追加します。

〜/ djangoreactproject / frontend / src / CustomerCreateUpdate.js

...
componentDidMount(){
    const { match: { params } } =  this.props;
    if(params  &&  params.pk)
    {
        customersService.getCustomer(params.pk).then((c)=>{
            this.refs.firstName.value  =  c.first_name;
            this.refs.lastName.value  =  c.last_name;
            this.refs.email.value  =  c.email;
            this.refs.phone.value  =  c.phone;
            this.refs.address.value  =  c.address;
            this.refs.description.value  =  c.description;
        })
    }
}

これはファイルの完全な内容です:

〜/ djangoreactproject / frontend / src / CustomerCreateUpdate.js

import React, { Component } from 'react';
import CustomersService from './CustomersService';

const customersService = new CustomersService();

class CustomerCreateUpdate extends Component {
    constructor(props) {
        super(props);
    
        this.handleSubmit = this.handleSubmit.bind(this);
      }

      componentDidMount(){
        const { match: { params } } = this.props;
        if(params && params.pk)
        {
          customersService.getCustomer(params.pk).then((c)=>{
            this.refs.firstName.value = c.first_name;
            this.refs.lastName.value = c.last_name;
            this.refs.email.value = c.email;
            this.refs.phone.value = c.phone;
            this.refs.address.value = c.address;
            this.refs.description.value = c.description;
          })
        }
      }

      handleCreate(){
        customersService.createCustomer(
          {
            "first_name": this.refs.firstName.value,
            "last_name": this.refs.lastName.value,
            "email": this.refs.email.value,
            "phone": this.refs.phone.value,
            "address": this.refs.address.value,
            "description": this.refs.description.value
        }          
        ).then((result)=>{
          alert("Customer created!");
        }).catch(()=>{
          alert('There was an error! Please re-check your form.');
        });
      }
      handleUpdate(pk){
        customersService.updateCustomer(
          {
            "pk": pk,
            "first_name": this.refs.firstName.value,
            "last_name": this.refs.lastName.value,
            "email": this.refs.email.value,
            "phone": this.refs.phone.value,
            "address": this.refs.address.value,
            "description": this.refs.description.value
        }          
        ).then((result)=>{
          console.log(result);
          alert("Customer updated!");
        }).catch(()=>{
          alert('There was an error! Please re-check your form.');
        });
      }
      handleSubmit(event) {
        const { match: { params } } = this.props;

        if(params && params.pk){
          this.handleUpdate(params.pk);
        }
        else
        {
          this.handleCreate();
        }

        event.preventDefault();
      }
    
      render() {
        return (
          <form onSubmit={this.handleSubmit}>
          <div className="form-group">
            <label>
              First Name:</label>
              <input className="form-control" type="text" ref='firstName' />
            
            <label>
              Last Name:</label>
              <input className="form-control" type="text" ref='lastName'/>
            
            <label>
              Phone:</label>
              <input className="form-control" type="text" ref='phone' />
            
            <label>
              Email:</label>
              <input className="form-control" type="text" ref='email' />
            
            <label>
              Address:</label>
              <input className="form-control" type="text" ref='address' />
            
            <label>
              Description:</label>
              <textarea className="form-control" ref='description' ></textarea>
              

            <input className="btn btn-primary" type="submit" value="Submit" />
            </div>
          </form>
        );
      }  
}

export default CustomerCreateUpdate;

CustomerCreateUpdateコンポーネントを作成したら、メインのAppコンポーネントを更新して、作成したさまざまなコンポーネントへのリンクを追加できます。

ステップ9—メインアプリコンポーネントを更新する

このセクションでは、アプリケーションのAppコンポーネントを更新して、前の手順で作成したコンポーネントへのリンクを作成します。

frontendフォルダーから、次のコマンドを実行して Reactルーターをインストールします。これにより、さまざまなReactコンポーネント間にルーティングとナビゲーションを追加できます。

cd ~/djangoreactproject/frontend
npm install --save react-router-dom

次に、~/djangoreactproject/frontend/src/App.jsを開きます。

nano ~/djangoreactproject/frontend/src/App.js

そこにあるものをすべて削除し、次のコードを追加して、ルーティングを追加するために必要なクラスをインポートします。 これらには、ルーターコンポーネントを作成するBrowserRouter、およびルートコンポーネントを作成するRouteが含まれます。

〜/ djangoreactproject / frontend / src / App.js

import  React, { Component } from  'react';
import { BrowserRouter } from  'react-router-dom'
import { Route, Link } from  'react-router-dom'
import  CustomersList  from  './CustomersList'
import  CustomerCreateUpdate  from  './CustomerCreateUpdate'
import  './App.css';

BrowserRouter は、HTML5履歴APIを使用してUIをURLと同期させます。

次に、BrowserRouterコンポーネントによってラップされる基本コンポーネントを提供する基本レイアウトを作成します。

〜/ djangoreactproject / frontend / src / App.js

...

const  BaseLayout  = () => (
<div  className="container-fluid">
    <nav  className="navbar navbar-expand-lg navbar-light bg-light">
        <a  className="navbar-brand"  href="#">Django React Demo</a>
        <button  className="navbar-toggler"  type="button"  data-toggle="collapse"  data-target="#navbarNavAltMarkup"  aria-controls="navbarNavAltMarkup"  aria-expanded="false"  aria-label="Toggle navigation">
        <span  className="navbar-toggler-icon"></span>
    </button>
    <div  className="collapse navbar-collapse"  id="navbarNavAltMarkup">
        <div  className="navbar-nav">
            <a  className="nav-item nav-link"  href="/">CUSTOMERS</a>
            <a  className="nav-item nav-link"  href="/customer">CREATE CUSTOMER</a>
        </div>
    </div>
    </nav>
    <div  className="content">
        <Route  path="/"  exact  component={CustomersList}  />
        <Route  path="/customer/:pk"  component={CustomerCreateUpdate}  />
        <Route  path="/customer/"  exact  component={CustomerCreateUpdate}  />
    </div>
</div>
)

Routeコンポーネントを使用して、アプリケーションのルートを定義します。 一致するものが見つかったら、ルータがロードする必要のあるコンポーネント。 各ルートには、照合するパスを指定するためのpathと、ロードするコンポーネントを指定するためのcomponentが必要です。 exactプロパティは、ルーターに正確なパスを一致させるように指示します。

最後に、ReactアプリケーションのルートまたはトップレベルコンポーネントであるAppコンポーネントを作成します。

〜/ djangoreactproject / frontend / src / App.js

...

class  App  extends  Component {

render() {
    return (
    <BrowserRouter>
        <BaseLayout/>
    </BrowserRouter>
    );
}
}
export  default  App;

このアプリはブラウザで実行することを目的としているため、BaseLayoutコンポーネントをBrowserRouterコンポーネントでラップしました。

完成したファイルは次のようになります。

〜/ djangoreactproject / frontend / src / App.js

import React, { Component } from 'react';
import { BrowserRouter } from 'react-router-dom'
import { Route, Link } from 'react-router-dom'

import  CustomersList from './CustomersList'
import  CustomerCreateUpdate  from './CustomerCreateUpdate'
import './App.css';

const BaseLayout = () => (
  <div className="container-fluid">
<nav className="navbar navbar-expand-lg navbar-light bg-light">
  <a className="navbar-brand" href="#">Django React Demo</a>
  <button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span className="navbar-toggler-icon"></span>
  </button>
  <div className="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div className="navbar-nav">
      <a className="nav-item nav-link" href="/">CUSTOMERS</a>
      <a className="nav-item nav-link" href="/customer">CREATE CUSTOMER</a>
      
    </div>
  </div>
</nav>  

    <div className="content">
      <Route path="/" exact component={CustomersList} />
      <Route path="/customer/:pk"  component={CustomerCreateUpdate} />
      <Route path="/customer/" exact component={CustomerCreateUpdate} />

    </div>

  </div>
)

class App extends Component {
  render() {
    return (
      <BrowserRouter>
        <BaseLayout/>
      </BrowserRouter>
    );
  }
}

export default App;

アプリケーションにルーティングを追加したら、アプリケーションをテストする準備が整いました。 http://localhost:3000に移動します。 アプリケーションの最初のページが表示されます。

このアプリケーションを配置すると、CRMアプリケーションのベースができあがります。

結論

このチュートリアルでは、DjangoとReactを使用してデモアプリケーションを作成しました。 DjangoRESTフレームワークを使用してRESTAPIを構築し、Axiosを使用してAPIを使用し、Bootstrap4を使用してCSSのスタイルを設定しました。 このプロジェクトのソースコードは、このGitHubリポジトリにあります。

このチュートリアルのセットアップでは、フロントエンドアプリとバックエンドアプリを別々に使用しました。 ReactをDjangoと統合するための別のアプローチについては、このtutorialとこのtutorialを確認してください。

Djangoを使用したアプリケーションの構築の詳細については、Django開発シリーズをフォローしてください。 公式のDjangoドキュメントもご覧ください。