DjangoとReactを使用してTo-Doアプリケーションを構築する方法
序章
このチュートリアルでは、DjangoとReactを使用してTo-Doアプリケーションを構築します。
Reactは、SPA(シングルページアプリケーション)を開発するためのJavaScriptフレームワークです。 堅実なドキュメントとその周りの活気に満ちたエコシステムがあります。
Djangoは、Web開発の一般的な方法を簡素化するPythonWebフレームワークです。 Djangoは信頼性が高く、一般的な開発ニーズをサポートする安定したライブラリの活気に満ちたエコシステムも備えています。
このアプリケーションでは、Reactはフロントエンドまたはクライアント側のフレームワークとして機能し、ユーザーインターフェースを処理し、Django RESTフレームワーク(DRF)を使用して構築されたAPIであるDjangoバックエンドへのリクエストを介してデータを取得および設定します。
このチュートリアルを終了すると、完全に機能するアプリケーションができあがります。
注:このチュートリアルのソースコードはGitHubで入手できます。
警告:このチュートリアルで提供されるコードは教育目的であり、本番環境での使用を目的としたものではありません。
このアプリケーションを使用すると、ユーザーはタスクを作成して、それらを完了または未完了としてマークできます。
前提条件
このチュートリアルに従うには、次のことを行う必要があります。
このチュートリアルは、Python v3.9.1、pip
v20.2.4、Django v3.1.6、djangorestframework
v3.12.2、django-cors-headers
v3.7.0、ノードv15.8.0、 npm
v7.5.4、React v17.0.1、およびaxios
v0.21.0。
ステップ1—バックエンドを設定する
このセクションでは、新しいプロジェクトディレクトリを作成し、Djangoをインストールします。
新しいターミナルウィンドウを開き、次のコマンドを実行して新しいプロジェクトディレクトリを作成します。
- mkdir django-todo-react
次に、ディレクトリに移動します。
- cd django-todo-react
次に、pip
を使用してPipenvをインストールします。
- pip install pipenv
注:インストールによっては、pip
の代わりにpip3
を使用する必要がある場合があります。
そして、新しい仮想環境をアクティブ化します。
- pipenv shell
Pipenvを使用してDjangoをインストールします。
- pipenv install django
次に、backend
という名前の新しいプロジェクトを作成します。
- django-admin startproject backend
次に、新しく作成されたバックエンドディレクトリに移動します。
- cd backend
todo
という新しいアプリケーションを起動します。
python manage.py startapp todo
移行を実行します。
python manage.py migrate
そして、サーバーを起動します。
python manage.py runserver
Webブラウザでhttp://localhost:8000
に移動します。
この時点で、Djangoアプリケーションのインスタンスが正常に実行されていることがわかります。 終了したら、サーバーを停止できます(CONTROL+C
またはCTRL+C
)。
todo
アプリケーションの登録
バックエンドのセットアップが完了したので、todo
アプリケーションをインストール済みアプリとして登録し、Djangoが認識できるようにすることができます。
コードエディタでbackend/settings.py
ファイルを開き、todo
をINSTALLED_APPS
に追加します。
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'todo',
]
次に、変更を保存します。
Todo
モデルの定義
Todo
アイテムをデータベースに保存する方法を定義するモデルを作成しましょう。
コードエディタでtodo/models.py
ファイルを開き、次のコード行を追加します。
from django.db import models
# Create your models here.
class Todo(models.Model):
title = models.CharField(max_length=120)
description = models.TextField()
completed = models.BooleanField(default=False)
def _str_(self):
return self.title
上記のコードスニペットは、Todoモデルの3つのプロパティについて説明しています。
title
description
completed
completed
プロパティは、タスクのステータスです。 タスクはいつでも完了するか、完了しないかのいずれかです。 Todo
モデルを作成したので、移行ファイルを作成する必要があります。
- python manage.py makemigrations todo
そして、変更をデータベースに適用します。
- python manage.py migrate todo
Djangoがデフォルトで提供する管理インターフェースを使用して作成したTodo
モデルでCRUD操作が機能することをテストできます。
コードエディタでtodo/admin.py
ファイルを開き、次のコード行を追加します。
from django.contrib import admin
from .models import Todo
class TodoAdmin(admin.ModelAdmin):
list_display = ('title', 'description', 'completed')
# Register your models here.
admin.site.register(Todo, TodoAdmin)
次に、変更を保存します。
管理インターフェースにアクセスするには、「スーパーユーザー」アカウントを作成する必要があります。 ターミナルで次のコマンドを実行します。
- python manage.py createsuperuser
スーパーユーザーのユーザー名、電子メール、およびパスワードを入力するように求められます。 管理ダッシュボードにログインするために必要になるため、覚えておくことができる詳細を必ず入力してください。
サーバーをもう一度起動します。
- python manage.py runserver
Webブラウザでhttp://localhost:8000/admin
に移動します。 そして、以前に作成したユーザー名とパスワードでログインします。
次のインターフェイスを使用して、Todo
アイテムを作成、編集、および削除できます。
このインターフェースを試した後、サーバーを停止できます(CONTROL+C
またはCTRL+C
)。
ステップ2—APIを設定する
このセクションでは、DjangoRESTフレームワークを使用してAPIを作成します。
Pipenvを使用してdjangorestframework
およびdjango-cors-headers
をインストールします。
- pipenv install djangorestframework django-cors-headers
インストールされているアプリケーションのリストにrest_framework
とcorsheaders
を追加する必要があります。 コードエディタでbackend/settings.py
ファイルを開き、INSTALLED_APPS
セクションとMIDDLEWARE
セクションを更新します。
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'corsheaders',
'rest_framework',
'todo',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'corsheaders.middleware.CorsMiddleware',
]
次に、次のコード行をbackend/settings.py
ファイルの最後に追加します。
CORS_ORIGIN_WHITELIST = [
'http://localhost:3000'
]
django-cors-headers
は、CORSルールが原因で通常発生するエラーを防ぐPythonライブラリです。 CORS_ORIGIN_WHITELIST
コードでは、アプリケーションのフロントエンド(そのポートで提供される)がAPIと対話するようにするため、localhost:3000
をホワイトリストに登録しました。
serializers
を作成しています
フロントエンドが受信したデータを処理できるように、モデルインスタンスをJSONに変換するシリアライザーが必要になります。
コードエディタでtodo/serializers.py
ファイルを作成します。 serializers.py
ファイルを開き、次のコード行で更新します。
from rest_framework import serializers
from .models import Todo
class TodoSerializer(serializers.ModelSerializer):
class Meta:
model = Todo
fields = ('id', 'title', 'description', 'completed')
このコードは、操作するモデルとJSONに変換するフィールドを指定します。
ビューの作成
todo/views.py
ファイルにTodoView
クラスを作成する必要があります。
コードエディタでtodo/views.py
ファイルを開き、次のコード行を追加します。
from django.shortcuts import render
from rest_framework import viewsets
from .serializers import TodoSerializer
from .models import Todo
# Create your views here.
class TodoView(viewsets.ModelViewSet):
serializer_class = TodoSerializer
queryset = Todo.objects.all()
viewsets
基本クラスは、デフォルトでCRUD操作の実装を提供します。 このコードは、serializer_class
とqueryset
を指定します。
コードエディタでbackend/urls.py
ファイルを開き、内容を次のコード行に置き換えます。
from django.contrib import admin
from django.urls import path, include
from rest_framework import routers
from todo import views
router = routers.DefaultRouter()
router.register(r'todos', views.TodoView, 'todo')
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include(router.urls)),
]
このコードは、APIのURLパスを指定します。 これは、APIの構築を完了する最後のステップでした。
Todo
モデルでCRUD操作を実行できるようになりました。 routerクラスを使用すると、次のクエリを実行できます。
/todos/
-すべてのTodo
アイテムのリストを返します。CREATE
およびREAD
操作はここで実行できます。/todos/id
–id
主キーを使用して、単一のTodo
アイテムを返します。UPDATE
およびDELETE
操作はここで実行できます。
サーバーを再起動しましょう:
- python manage.py runserver
Webブラウザでhttp://localhost:8000/api/todos
に移動します。
次のインターフェイスを使用して、新しいTodoアイテムをCREATE
できます。
Todoアイテムが正常に作成されると、正常な応答が表示されます。
id
主キーを使用して、特定のTodo
アイテムに対してDELETE
およびUPDATE
操作を実行することもできます。 アドレス構造/api/todos/{id}
を使用し、id
を提供します。
URLに1
を追加して、id
が「1」のTodoアイテムを調べます。 Webブラウザでhttp://localhost:8000/api/todos/1
に移動します。
これで、アプリケーションのバックエンドの構築が完了しました。
ステップ3—フロントエンドの設定
アプリケーションのバックエンドが完成したので、フロントエンドを作成し、作成したインターフェイスを介してバックエンドと通信させることができます。
まず、新しいターミナルウィンドウを開き、django-todo-react
プロジェクトディレクトリに移動します。
フロントエンドを設定するために、このチュートリアルはCreateReactAppに依存します。 create-react-app
を使用するにはいくつかのアプローチがあります。 1つのアプローチは、npx
を使用してパッケージを実行し、プロジェクトを作成することです。
- npx create-react-app frontend
Create React Appを使用してReactプロジェクトをセットアップする方法を読むと、このアプローチの詳細を学ぶことができます。
プロジェクトが作成されたら、新しく作成されたfrontend
ディレクトリに変更できます。
- cd frontend
次に、アプリケーションを起動します。
- npm start
Webブラウザがhttp://localhost:3000
を開き、デフォルトのCreateReactApp画面が表示されます。
次に、bootstrap
とreactstrap
をインストールして、ユーザーインターフェイスツールを提供します。
- npm install bootstrap@4.6.0 reactstrap@8.9.0 --legacy-peer-deps
注: React、Bootstrap、およびReactstrapのバージョンによっては、unable to resolve dependency tree
エラーが発生する場合があります。
改訂の時点で、popper.js
の最新バージョンは非推奨になっており、React17+と競合します。 これは既知の問題であり、インストール時に--legacy-peer-deps
オプションを使用することができます。
コードエディタでindex.js
を開き、bootstrap.min.css
を追加します。
import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.css';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
この手順で問題が発生した場合は、ブートストラップを追加するための公式ドキュメントを参照してください。
コードエディタでApp.js
を開き、次のコード行を追加します。
import React, { Component } from "react";
const todoItems = [
{
id: 1,
title: "Go to Market",
description: "Buy ingredients to prepare dinner",
completed: true,
},
{
id: 2,
title: "Study",
description: "Read Algebra and History textbook for the upcoming test",
completed: false,
},
{
id: 3,
title: "Sammy's books",
description: "Go to library to return Sammy's books",
completed: true,
},
{
id: 4,
title: "Article",
description: "Write article on how to use Django with React",
completed: false,
},
];
class App extends Component {
constructor(props) {
super(props);
this.state = {
viewCompleted: false,
todoList: todoItems,
};
}
displayCompleted = (status) => {
if (status) {
return this.setState({ viewCompleted: true });
}
return this.setState({ viewCompleted: false });
};
renderTabList = () => {
return (
<div className="nav nav-tabs">
<span
className={this.state.viewCompleted ? "nav-link active" : "nav-link"}
onClick={() => this.displayCompleted(true)}
>
Complete
</span>
<span
className={this.state.viewCompleted ? "nav-link" : "nav-link active"}
onClick={() => this.displayCompleted(false)}
>
Incomplete
</span>
</div>
);
};
renderItems = () => {
const { viewCompleted } = this.state;
const newItems = this.state.todoList.filter(
(item) => item.completed == viewCompleted
);
return newItems.map((item) => (
<li
key={item.id}
className="list-group-item d-flex justify-content-between align-items-center"
>
<span
className={`todo-title mr-2 ${
this.state.viewCompleted ? "completed-todo" : ""
}`}
title={item.description}
>
{item.title}
</span>
<span>
<button
className="btn btn-secondary mr-2"
>
Edit
</button>
<button
className="btn btn-danger"
>
Delete
</button>
</span>
</li>
));
};
render() {
return (
<main className="container">
<h1 className="text-white text-uppercase text-center my-4">Todo app</h1>
<div className="row">
<div className="col-md-6 col-sm-10 mx-auto p-0">
<div className="card p-3">
<div className="mb-4">
<button
className="btn btn-primary"
>
Add task
</button>
</div>
{this.renderTabList()}
<ul className="list-group list-group-flush border-top-0">
{this.renderItems()}
</ul>
</div>
</div>
</div>
</main>
);
}
}
export default App;
このコードには、4つのアイテムのハードコードされた値が含まれています。 これらは、アイテムがバックエンドからフェッチされるまでの一時的な値になります。
renderTabList()
関数は、表示されるアイテムのセットを制御するのに役立つ2つのスパンをレンダリングします。 完了タブをクリックすると、完了したタスクが表示されます。 不完全タブをクリックすると、不完全なタスクが表示されます。
変更を保存し、Webブラウザでアプリケーションを確認します。
タスクの追加や編集などのアクションを処理するには、モーダルコンポーネントを作成する必要があります。
まず、src
ディレクトリにcomponents
フォルダを作成します。
- mkdir src/components
次に、Modal.js
ファイルを作成し、コードエディタで開きます。 次のコード行を追加します。
import React, { Component } from "react";
import {
Button,
Modal,
ModalHeader,
ModalBody,
ModalFooter,
Form,
FormGroup,
Input,
Label,
} from "reactstrap";
export default class CustomModal extends Component {
constructor(props) {
super(props);
this.state = {
activeItem: this.props.activeItem,
};
}
handleChange = (e) => {
let { name, value } = e.target;
if (e.target.type === "checkbox") {
value = e.target.checked;
}
const activeItem = { ...this.state.activeItem, [name]: value };
this.setState({ activeItem });
};
render() {
const { toggle, onSave } = this.props;
return (
<Modal isOpen={true} toggle={toggle}>
<ModalHeader toggle={toggle}>Todo Item</ModalHeader>
<ModalBody>
<Form>
<FormGroup>
<Label for="todo-title">Title</Label>
<Input
type="text"
id="todo-title"
name="title"
value={this.state.activeItem.title}
onChange={this.handleChange}
placeholder="Enter Todo Title"
/>
</FormGroup>
<FormGroup>
<Label for="todo-description">Description</Label>
<Input
type="text"
id="todo-description"
name="description"
value={this.state.activeItem.description}
onChange={this.handleChange}
placeholder="Enter Todo description"
/>
</FormGroup>
<FormGroup check>
<Label check>
<Input
type="checkbox"
name="completed"
checked={this.state.activeItem.completed}
onChange={this.handleChange}
/>
Completed
</Label>
</FormGroup>
</Form>
</ModalBody>
<ModalFooter>
<Button
color="success"
onClick={() => onSave(this.state.activeItem)}
>
Save
</Button>
</ModalFooter>
</Modal>
);
}
}
このコードはCustomModal
クラスを作成し、reactstrap
ライブラリから派生したModalコンポーネントをネストします。
このコードは、次の形式で3つのフィールドも定義しました。
title
description
completed
これらは、バックエンドのTodoモデルのプロパティとして定義したものと同じフィールドです。
CustomModal
は、activeItem
、toggle
、およびonSave
を小道具として受け取ります。
activeItem
は、編集するTodoアイテムを表します。toggle
は、モーダルの状態を制御するために使用される関数です(つまり、モーダルを開いたり閉じたりします)。onSave
は、Todoアイテムの編集された値を保存するために呼び出される関数です。
次に、CustomModal
コンポーネントをApp.js
ファイルにインポートします。
コードエディタでsrc/App.js
ファイルに再度アクセスし、内容全体を次のコード行に置き換えます。
import React, { Component } from "react";
import Modal from "./components/Modal";
const todoItems = [
{
id: 1,
title: "Go to Market",
description: "Buy ingredients to prepare dinner",
completed: true,
},
{
id: 2,
title: "Study",
description: "Read Algebra and History textbook for the upcoming test",
completed: false,
},
{
id: 3,
title: "Sammy's books",
description: "Go to library to return Sammy's books",
completed: true,
},
{
id: 4,
title: "Article",
description: "Write article on how to use Django with React",
completed: false,
},
];
class App extends Component {
constructor(props) {
super(props);
this.state = {
viewCompleted: false,
todoList: todoItems,
modal: false,
activeItem: {
title: "",
description: "",
completed: false,
},
};
}
toggle = () => {
this.setState({ modal: !this.state.modal });
};
handleSubmit = (item) => {
this.toggle();
alert("save" + JSON.stringify(item));
};
handleDelete = (item) => {
alert("delete" + JSON.stringify(item));
};
createItem = () => {
const item = { title: "", description: "", completed: false };
this.setState({ activeItem: item, modal: !this.state.modal });
};
editItem = (item) => {
this.setState({ activeItem: item, modal: !this.state.modal });
};
displayCompleted = (status) => {
if (status) {
return this.setState({ viewCompleted: true });
}
return this.setState({ viewCompleted: false });
};
renderTabList = () => {
return (
<div className="nav nav-tabs">
<span
className={this.state.viewCompleted ? "nav-link active" : "nav-link"}
onClick={() => this.displayCompleted(true)}
>
Complete
</span>
<span
className={this.state.viewCompleted ? "nav-link" : "nav-link active"}
onClick={() => this.displayCompleted(false)}
>
Incomplete
</span>
</div>
);
};
renderItems = () => {
const { viewCompleted } = this.state;
const newItems = this.state.todoList.filter(
(item) => item.completed === viewCompleted
);
return newItems.map((item) => (
<li
key={item.id}
className="list-group-item d-flex justify-content-between align-items-center"
>
<span
className={`todo-title mr-2 ${
this.state.viewCompleted ? "completed-todo" : ""
}`}
title={item.description}
>
{item.title}
</span>
<span>
<button
className="btn btn-secondary mr-2"
onClick={() => this.editItem(item)}
>
Edit
</button>
<button
className="btn btn-danger"
onClick={() => this.handleDelete(item)}
>
Delete
</button>
</span>
</li>
));
};
render() {
return (
<main className="container">
<h1 className="text-white text-uppercase text-center my-4">Todo app</h1>
<div className="row">
<div className="col-md-6 col-sm-10 mx-auto p-0">
<div className="card p-3">
<div className="mb-4">
<button
className="btn btn-primary"
onClick={this.createItem}
>
Add task
</button>
</div>
{this.renderTabList()}
<ul className="list-group list-group-flush border-top-0">
{this.renderItems()}
</ul>
</div>
</div>
</div>
{this.state.modal ? (
<Modal
activeItem={this.state.activeItem}
toggle={this.toggle}
onSave={this.handleSubmit}
/>
) : null}
</main>
);
}
}
export default App;
変更を保存し、Webブラウザでアプリケーションを確認します。
Todo
アイテムを編集して保存しようとすると、Todo
アイテムのオブジェクトを表示するアラートが表示されます。 保存または削除をクリックすると、Todo
アイテムに対してそれぞれのアクションが実行されます。
注::ReactおよびReactstrapのバージョンによっては、コンソールエラーが発生する場合があります。 改訂時点では、Warning: Legacy context API has been detected within a strict-mode tree.
とWarning: findDOMNode is deprecated in StrictMode.
は既知の問題です。
次に、前のセクションで作成したDjangoAPIと相互作用するようにアプリケーションを変更します。 最初のターミナルウィンドウに戻り、サーバーが実行されていることを確認します。 実行されていない場合は、次のコマンドを使用します。
- python manage.py runserver
注:このターミナルウィンドウを閉じた場合は、backend
ディレクトリに移動して、仮想Pipenvシェルを使用する必要があることに注意してください。
バックエンドサーバー上のAPIエンドポイントにリクエストを送信するには、axios
というJavaScriptライブラリをインストールします。
2番目のターミナルウィンドウで、frontend
ディレクトリにいることを確認し、axios
をインストールします。
- npm install axios@0.21.1
次に、コードエディタでfrontend/package.json
ファイルを開き、proxy
を追加します。
[...]
"name": "frontend",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:8000",
"dependencies": {
"axios": "^0.18.0",
"bootstrap": "^4.1.3",
"react": "^16.5.2",
"react-dom": "^16.5.2",
"react-scripts": "2.0.5",
"reactstrap": "^6.5.0"
},
[...]
プロキシは、Djangoアプリケーションが処理するhttp://localhost:8000
へのAPIリクエストのトンネリングに役立ちます。 このproxy
がないと、フルパスを指定する必要があります。
axios.get("http://localhost:8000/api/todos/")
proxy
を使用すると、相対パスを提供できます。
axios.get("/api/todos/")
注:プロキシをアプリケーションに登録するには、開発サーバーを再起動する必要がある場合があります。
frontend/src/App.js
ファイルに再度アクセスし、コードエディタで開きます。 この手順では、ハードコードされたtodoItems
を削除し、バックエンドサーバーへのリクエストからのデータを使用します。 handleSubmit
およびhandleDelete
App.js
ファイルを開き、次の最終バージョンに置き換えます。
import React, { Component } from "react";
import Modal from "./components/Modal";
import axios from "axios";
class App extends Component {
constructor(props) {
super(props);
this.state = {
viewCompleted: false,
todoList: [],
modal: false,
activeItem: {
title: "",
description: "",
completed: false,
},
};
}
componentDidMount() {
this.refreshList();
}
refreshList = () => {
axios
.get("/api/todos/")
.then((res) => this.setState({ todoList: res.data }))
.catch((err) => console.log(err));
};
toggle = () => {
this.setState({ modal: !this.state.modal });
};
handleSubmit = (item) => {
this.toggle();
if (item.id) {
axios
.put(`/api/todos/${item.id}/`, item)
.then((res) => this.refreshList());
return;
}
axios
.post("/api/todos/", item)
.then((res) => this.refreshList());
};
handleDelete = (item) => {
axios
.delete(`/api/todos/${item.id}/`)
.then((res) => this.refreshList());
};
createItem = () => {
const item = { title: "", description: "", completed: false };
this.setState({ activeItem: item, modal: !this.state.modal });
};
editItem = (item) => {
this.setState({ activeItem: item, modal: !this.state.modal });
};
displayCompleted = (status) => {
if (status) {
return this.setState({ viewCompleted: true });
}
return this.setState({ viewCompleted: false });
};
renderTabList = () => {
return (
<div className="nav nav-tabs">
<span
onClick={() => this.displayCompleted(true)}
className={this.state.viewCompleted ? "nav-link active" : "nav-link"}
>
Complete
</span>
<span
onClick={() => this.displayCompleted(false)}
className={this.state.viewCompleted ? "nav-link" : "nav-link active"}
>
Incomplete
</span>
</div>
);
};
renderItems = () => {
const { viewCompleted } = this.state;
const newItems = this.state.todoList.filter(
(item) => item.completed === viewCompleted
);
return newItems.map((item) => (
<li
key={item.id}
className="list-group-item d-flex justify-content-between align-items-center"
>
<span
className={`todo-title mr-2 ${
this.state.viewCompleted ? "completed-todo" : ""
}`}
title={item.description}
>
{item.title}
</span>
<span>
<button
className="btn btn-secondary mr-2"
onClick={() => this.editItem(item)}
>
Edit
</button>
<button
className="btn btn-danger"
onClick={() => this.handleDelete(item)}
>
Delete
</button>
</span>
</li>
));
};
render() {
return (
<main className="container">
<h1 className="text-white text-uppercase text-center my-4">Todo app</h1>
<div className="row">
<div className="col-md-6 col-sm-10 mx-auto p-0">
<div className="card p-3">
<div className="mb-4">
<button
className="btn btn-primary"
onClick={this.createItem}
>
Add task
</button>
</div>
{this.renderTabList()}
<ul className="list-group list-group-flush border-top-0">
{this.renderItems()}
</ul>
</div>
</div>
</div>
{this.state.modal ? (
<Modal
activeItem={this.state.activeItem}
toggle={this.toggle}
onSave={this.handleSubmit}
/>
) : null}
</main>
);
}
}
export default App;
refreshList()
関数は再利用可能であり、APIリクエストが完了するたびに呼び出されます。 Todoリストを更新して、追加されたアイテムの最新のリストを表示します。
handleSubmit()
関数は、作成操作と更新操作の両方を処理します。 パラメータとして渡されたアイテムにid
がない場合は、作成されていない可能性があるため、関数が作成します。
この時点で、バックエンドサーバーが最初のターミナルウィンドウで実行されていることを確認します。
- python manage.py runserver
注:このターミナルウィンドウを閉じた場合は、backend
ディレクトリに移動して、仮想Pipenvシェルを使用する必要があることに注意してください。
そして、2番目のターミナルウィンドウで、frontend
ディレクトリにいることを確認し、フロントエンドアプリケーションを起動します。
- npm start
これで、Webブラウザでhttp://localhost:3000
にアクセスすると、アプリケーションでREAD
、CREATE
、UPDATE
、およびDELETE
のタスクを実行できるようになります。 。
これで、Todoアプリケーションのフロントエンドとバックエンドが完成しました。
結論
この記事では、DjangoとReactを使用してTo-Doアプリケーションを構築しました。 これは、djangorestframework
、django-cors-headers
、axios
、bootstrap
、およびreactstrap
ライブラリで実現しました。
Djangoについて詳しく知りたい場合は、Djangoトピックページで演習とプログラミングプロジェクトを確認してください。
Reactの詳細については、 React.js シリーズのコーディング方法をご覧になるか、Reactトピックページで演習やプログラミングプロジェクトを確認してください。