2.1 全体的なアーキテクチャ
この段階では、タスク管理アプリケーションのアーキテクチャを設計するよ。Frontend、Backend、Databaseがどのように相互作用するか、それぞれにどんなコンポーネントが含まれるかを決めるんだ。
アプリケーションは以下の3つの主要なコンポーネントから構成されるよ:
- Frontend (ReactJS): ユーザーとシステムがやり取りするためのクライアントサイド。
- Backend (Flask): Frontendからのリクエストを処理し、Databaseとやり取りするサーバーサイド。
- Database (PostgreSQL): ユーザーとタスクのデータを保存するデータストア。
アーキテクチャは以下のようになるんだ:
ターミナル
+-------------+ +-------------+ +--------------+
| | | | | |
| Frontend +------->+ Backend +------->+ Database |
| (ReactJS) | | (Flask) | | (PostgreSQL) |
| | | | | |
+-------------+ +-------------+ +--------------+
コンポーネント間の相互作用
- Frontend: タスクのCRUD操作(作成、読み取り、更新、削除)を実行するために、BackendにHTTPリクエストを送信するんだ。
- Backend: FrontendからのHTTPリクエストを処理して、ビジネスロジックを実行し、Databaseとやり取りを行うよ。
- Database: Backendからのリクエストに応じてデータを保存したり、提供したりするんだ。
2.2 各コンポーネントの説明
1. Frontend (ReactJS):
- インターフェースコンポーネント: ユーザー登録・認証、タスクの作成と編集、タスクリストの閲覧用コンポーネント。
- APIとのやり取り: HTTPリクエストをバックエンドに送信するためにAxiosライブラリを使用する。
2. Backend (Flask):
- REST API: ユーザーとタスクの管理用のエンドポイントを実装。
- データモデル: SQLAlchemyを使用してユーザーとタスクのデータモデルを定義。
- ビジネスロジック: データのバリデーションとユーザーセッション管理を含むアプリケーションロジックの処理。
3. Database (PostgreSQL):
- テーブル: ユーザー情報およびタスク情報を保存するためのテーブル。
- テーブル間の関係: ユーザーとタスクのテーブル間の関係を定義(例えば、1人のユーザーが複数のタスクを持つことができる)。
4. ネットワークインタラクション
全てのコンポーネント間の通信はHTTPプロトコルを通じて行われる。フロントエンドはREST APIを通じてバックエンドと連携し、バックエンドはSQLクエリを通じてデータベースと連携する。
- Frontend: 開発およびテスト用のポート3000。
- Backend: フロントエンドと連携するためのポート5000。
- Database: バックエンドと連携するためのポート5432。
2.3 各コンポーネントの詳細説明
1. 基本的なデータ構造
ユーザーとタスクのデータをPostgreSQLデータベースに保存するために、users
とtasks
の2つのテーブルを作成するよ。
users
テーブル:
-
id (int, primary key)
: ユーザーのユニークな識別子。 username (varchar, unique)
: ユーザー名。password (varchar)
: ユーザーのパスワードハッシュ。
tasks
テーブル:
-
id (int, primary key)
: タスクのユニークな識別子。 title (varchar)
: タスクのタイトル。description (text)
: タスクの説明。-
owner_id (int, foreign key)
: タスクが割り当てられたユーザーの識別子。 -
status (varchar)
: タスクのステータス (例えば、完了/未完了)。
2. API デザイン
バックエンドはフロントエンドと連携するためのRESTful APIを提供するよ。エンドポイントの例は以下の通り:
- ユーザー:
- POST /users: 新しいユーザーを作成。
- GET /users: すべてのユーザーリストを取得。
- GET /users/:id: 特定のユーザー情報を取得。
- PUT /users/:id: ユーザー情報を更新。
- DELETE /users/:id: ユーザーを削除。
- タスク:
- POST /tasks: 新しいタスクを作成。
- GET /tasks: すべてのタスクリストを取得。
- GET /tasks/:id: 特定のタスク情報を取得。
- PUT /tasks/:id: タスク情報を更新。
- DELETE /tasks/:id: タスクを削除。
2.4 データモデル
データベースのテーブルを操作するためのPythonコードは以下のようになります:
User Model:
Python
from app import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
password = db.Column(db.String(120), nullable=False)
tasks = db.relationship('Task', backref='owner', lazy=True)
def to_dict(self):
return {
"id": self.id,
"username": self.username
}
Task Model:
Python
from app import db
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(120), nullable=False)
description = db.Column(db.Text, nullable=True)
owner_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
status = db.Column(db.String(20), nullable=False, default="未完了")
def to_dict(self):
return {
"id": self.id,
"title": self.title,
"description": self.description,
"owner_id": self.owner_id,
"status": self.status
}
2.5 ルートとコントローラー
サーバー側でのAPI実装の例:
Python
from app import app, db
from app.models import Task, User
from flask import request, jsonify
@app.route('/tasks', methods=['GET'])
def get_tasks():
tasks = Task.query.all()
return jsonify([task.to_dict() for task in tasks])
@app.route('/tasks', methods=['POST'])
def create_task():
data = request.get_json()
new_task = Task(
title=data['title'],
description=data.get('description'),
owner_id=data['owner_id'],
status=data.get('status', "未完了")
)
db.session.add(new_task)
db.session.commit()
return jsonify(new_task.to_dict()), 201
@app.route('/tasks/<int:id>', methods=['GET'])
def get_task(id):
task = Task.query.get_or_404(id)
return jsonify(task.to_dict())
@app.route('/tasks/<int:id>', methods=['PUT'])
def update_task(id):
data = request.get_json()
task = Task.query.get_or_404(id)
task.title = data['title']
task.description = data.get('description')
task.status = data.get('status', task.status)
task.owner_id = data['owner_id']
db.session.commit()
return jsonify(task.to_dict())
@app.route('/tasks/<int:id>', methods=['DELETE'])
def delete_task(id):
task = Task.query.get_or_404(id)
db.session.delete(task)
db.session.commit()
return '', 204
2.6 フロントエンドからサーバーにリクエストする例
タスクのリストを表示するためのReactコンポーネントの例:
Javascript
import React, { useEffect, useState } from 'react';
import axios from 'axios';
const TaskList = () => {
const [tasks, setTasks] = useState([]);
useEffect(() => {
axios.get('http://localhost:5000/tasks')
.then(response => {
setTasks(response.data);
})
.catch(error => {
console.error('タスクの取得中にエラーが発生しました!', error);
});
}, []);
return (
<div>
<h1>タスクリスト</h1>
<ul>
{tasks.map(task => (
<li key={task.id}>{task.title} - {task.status}</li>
))}
</ul>
</div>
);
};
export default TaskList;
GO TO FULL VERSION