Djangoを使用して顧客情報を管理し、Ubuntu 18.04でReactする最新のWebアプリケーションを構築する方法

著者は、Write for DOnationsプログラムの一部として寄付を受け取るためにOpen Sourcing Mental Illness Ltdを選択しました。

前書き

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

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

  • React、開発者がRESTAPIバックエンド用のWebおよびネイティブフロントエンドを構築できるようにするJavaScriptフレームワーク。

  • Djangoは、model view controller (MVC)ソフトウェアアーキテクチャパターンに従う無料のオープンソースPythonWebフレームワークです。

  • Django REST framework、DjangoでRESTAPIを構築するための強力で柔軟なツールキット。

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

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

前提条件

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

[[step-1 -—- creating-a-python-virtual-environment-and-installing-dependencies]] ==ステップ1—Python仮想環境の作成と依存関係のインストール

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

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

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

cd ~
python3 -m venv ./env

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

source env/bin/activate

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

  • Django:プロジェクトのWebフレームワーク。

  • Django REST framework:DjangoでRESTAPIを構築するサードパーティアプリケーション。

  • django-cors-headers:CORSを有効にするパッケージ。

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

pip install django djangorestframework django-cors-headers

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

[[step-2 -—- creating-the-django-project]] ==ステップ2—Dj​​angoプロジェクトの作成

この手順では、次のコマンドとユーティリティを使用して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プロジェクトのディレクトリ構造を見てみましょう。

[。注意]##

Tip:treeは、コマンドラインからファイルとディレクトリの構造を表示するための便利なコマンドです。 次のコマンドでインストールできます:

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_APPSlistなどの変数が含まれます。 Djangoのドキュメントには、available settingsに関する詳細情報があります。

  • urls.py:このファイルには、URLパターンと関連するビューのリストが含まれています。 各パターンは、URLと、そのURLに対して呼び出す必要がある関数との間の接続をマップします。 URLとビューの詳細については、How To Create Django Viewsのチュートリアルを参照してください。

プロジェクトでの作業の最初のステップは、前のステップでインストールしたパッケージ(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クラスであるmiddlewaresのリストです。

~/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 = FalseCORS_ORIGIN_WHITELIST('localhost:3000',)の設定をsettings.pyファイルに追加します。 これらの設定をファイルの任意の場所に追加します。

~/djangoreactproject/djangoreactproject/settings.py

...
CORS_ORIGIN_ALLOW_ALL = False

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

django-cors-headers docsでより多くの構成オプションを見つけることができます。

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

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

python manage.py startapp customers

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

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

nano ~/djangoreactproject/djangoreactproject/settings.py

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

~/djangoreactproject/djangoreactproject/settings.py

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

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

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

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ブラウザでこのアドレスに移動すると、次のページが表示されます。

Django demo page

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

[[step-3 -—- creating-the-react-frontend]] ==ステップ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 demo page

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

このアプリケーションは、Bootstrap 4を使用して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命令です。

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

[[step-4 -—- creating-the-customer-model-and-initial-data]] ==ステップ4—顧客モデルと初期データの作成

DjangoアプリケーションとReactフロントエンドを作成したら、次のステップは、顧客に関する情報を保持するデータベーステーブルを表すCustomerモデルを作成することです。 DjangoObject 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ステートメントのおかげで、顧客モデルのAPIはすでにファイルにインポートされています。 ここで、models.Modelを拡張するCustomerクラスを追加します。 Djangoの各モデルは、django.db.models.Modelを拡張するPythonクラスです。

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

  • first_name —顧客の名。

  • last_name —顧客の姓。

  • email —顧客の電子メールアドレス。

  • phone —顧客の電話番号。

  • address —顧客の住所。

  • description —顧客の説明。

  • createdAt —顧客が追加された日付。

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

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

~/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

次に、data migration fileを使用して初期顧客データを作成します。 data migration fileは、データベース内のデータを追加または変更する移行です。 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から、移行を作成するためのDjango APIであるmigrationsAPIをインポートします。

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

  • dependencies:依存する移行が含まれます。

  • 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オブジェクトは、インストールされているアプリケーションとそのデータベースモデルのregistryを表します。

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

データ移行の詳細については、data migrations in 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

このプロセスの詳細については、How To Create Django Modelsを参照してください。

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

[[step-5 -—- creating-the-rest-api]] ==ステップ5— RESTAPIの作成

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

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

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

  • api/customers:このエンドポイントは、顧客を作成し、ページ付けされた顧客のセットを返すために使用されます。

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

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

Customerモデルのserializer classを作成することから始めましょう。

Serializerクラスの追加

顧客インスタンスとQuerySetをJSONとの間で変換するには、Customerモデルのシリアライザークラスを作成する必要があります。 シリアライザークラスを作成するには、最初に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およびDjango RESTフレームワークAPIとともにインポートします。

次に、POSTおよびGET HTTP要求を処理するためのビューを追加します。

~/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ビューを作成します。 decoratorは、別の関数を受け取り、それを動的に拡張する関数です。

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

  • GETリクエストの場合、メソッドはDjangoPaginatorを使用してデータをページ分割し、シリアル化後のデータの最初のページ、利用可能な顧客の数、利用可能なページの数、前のページと次のページへのリンクを返します。 Paginatorは、データのリストをページにページ分割し、各ページのアイテムにアクセスするメソッドを提供する組み込みのDjangoクラスです。

  • POSTリクエストの場合、このメソッドは受信した顧客データをシリアル化してから、シリアライザーオブジェクトのsave()メソッドを呼び出します。 次に、201ステータスコードを持つHttpResponseのインスタンスであるResponseオブジェクトを返します。 作成する各ビューは、HttpResponseオブジェクトを取得する責任があります。 save()メソッドは、シリアル化されたデータをデータベースに保存します。

HttpResponseとビューの詳細については、このcreating view functionsの説明を参照してください。

次に、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リクエストの場合、メソッドは顧客オブジェクトの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/は顧客のクエリと作成用で、api/customers/<pk>は単一の顧客を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 listに追加します。

~/djangoreactproject/djangoreactproject/urls.py

...

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

RESTエンドポイントを作成したら、それらを使用する方法を見てみましょう。

[[step-6 -—- sumption-the-rest-api-with-axios]] ==ステップ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

Django REST APIに接続するメソッドを含む次のコードを追加します。

~/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インターフェースに表示できるようになりました。

[[step-7 --- displaying-data-from-the-api-in-the-react-application]] ==ステップ7—ReactアプリケーションでAPIからのデータを表示する

このステップでは、CustomersList Reactcomponentを作成します。 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を拡張してREST APIを呼び出すCustomersListコンポーネントを作成します。 Reactコンポーネントはextend or subclass the Component classである必要があります。 E6クラスと継承の詳細については、Understanding Classes in 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;

constructor内で、stateオブジェクトを初期化しています。 これは、空のcustomersarrayを使用してコンポーネントの状態変数を保持します。 この配列は、顧客と、バックエンドAPIから取得する次のページのURLを保持するnextPageURLを保持します。 また、bindingnextPage()handleDelete()methodsから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})
    });
}

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

~/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() methodを追加します。これにより、コンポーネントの状態から顧客のテーブルがレンダリングされます。

~/djangoreactproject/frontend/src/CustomersList.js

...
render() {

    return (
    
{this.state.customers.map( c => )}
# First Name Last Name Phone Email Address Description Actions
{c.pk} {c.first_name} {c.last_name} {c.phone} {c.email} {c.address} {c.description} Update
); }

これは、ファイルの完全なコンテンツです。

~/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 (
        
{this.state.customers.map( c => )}
# First Name Last Name Phone Email Address Description Actions
{c.pk} {c.first_name} {c.last_name} {c.phone} {c.email} {c.address} {c.description} Update
); } } export default CustomersList;

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

[[step-8 -—- adding-the-customer-create-and-update-react-component]] ==ステップ8—顧客のCreate and UpdateReactコンポーネントの追加

このステップでは、顧客の作成と更新を処理する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 (
          
); }

このメソッドは、フォーム入力要素ごとに、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 (
          
); } } export default CustomerCreateUpdate;

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

[[step-9 -—- updating-the-main-app-component]] ==ステップ9—メインアプリコンポーネントの更新

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

frontendフォルダーから、次のコマンドを実行してReact Routerをインストールします。これにより、さまざまな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 history APIを使用してUIをURLと同期させます。

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

~/djangoreactproject/frontend/src/App.js

...

const  BaseLayout  = () => (

)

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

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

~/djangoreactproject/frontend/src/App.js

...

class  App  extends  Component {

render() {
    return (
    
        
    
    );
}
}
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 = () => (
  
)

class App extends Component {
  render() {
    return (
      
        
      
    );
  }
}

export default App;

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

Application Home Page

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

結論

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

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

Djangoを使用してアプリケーションを構築する方法の詳細については、Django development seriesをたどることができます。 official Django docsも確認できます。