序章

Flask は、Python言語を使用してWebアプリケーションを構築するためのフレームワークであり、 SQLite は、Pythonでアプリケーションデータを保存するために使用できるデータベースエンジンです。 このチュートリアルでは、FlaskとSQLiteを使用して構築されたアプリケーションに、多対多の関係を追加して変更します。

このチュートリアルは個別に実行できますが、FlaskおよびSQLiteを使用した1対多データベースの関係でアイテムを変更する方法チュートリアルの続きでもあります。 ToDoアプリケーションの例を使用した1対多の関係。 このアプリケーションを使用すると、ユーザーは新しいTo Doアイテムを追加したり、アイテムをさまざまなリストに分類したり、アイテムを変更したりできます。

多対多データベース関係は、各テーブルのレコードが他のテーブルの複数のレコードを参照できる2つのテーブル間の関係です。 たとえば、ブログでは、投稿用のテーブルは、作成者を保存するためのテーブルと多対多の関係を持つことができます。 各投稿は多くの作成者を参照でき、各作成者は多くの投稿を参照できます。 各投稿には多くのの作成者を含めることができ、各作成者は多くのの投稿を書き込むことができます。 したがって、投稿と作成者の間には多対多の関係があります。 別の例として、ソーシャルメディアアプリケーションでは、各投稿に多くのハッシュタグがあり、各ハッシュタグに多くの投稿がある場合があります。

チュートリアルが終了するまでに、アプリケーションには、さまざまなユーザーにToDoアイテムを割り当てるための新機能が追加されます。 assigneesという言葉でto-dosを割り当てられたユーザーを指します。 たとえば、あなたは家庭用のやることアイテムを持つことができます Cleaning the kitchen、両方に割り当てることができます SammyJo-各ToDoには、多くのの担当者(つまり、 SammyJo). また、各ユーザーは多くのタスクを割り当てることができます(つまり、 Sammy 複数のToDoアイテムを割り当てることができます)、これはToDoアイテムと担当者の間の多対多の関係です。

このチュートリアルの最後に、アプリケーションには、リストされた担当者の名前が記載された Assignedtoタグが含まれます。

前提条件

このガイドに従う前に、次のものが必要です。

  • ローカルのPython3プログラミング環境については、 Python3シリーズのローカルプログラミング環境をインストールしてセットアップする方法のチュートリアルに従ってください。 このチュートリアルでは、プロジェクトディレクトリを呼び出します flask_todo.

  • (オプション)ステップ1 では、このチュートリアルで作業するToDoアプリケーションのクローンを作成するオプションがあります。 ただし、オプションで、FlaskおよびSQLiteとの1対多のデータベース関係の使用方法およびFlaskおよびSQLiteとの1対多のデータベース関係のアイテムの変更方法を使用できます。 ]。 このページから最終コードにアクセスできます。

  • (オプション)ルートの作成、HTMLテンプレートのレンダリング、SQLiteデータベースへの接続などの基本的なFlaskの概念の理解。 これらの概念に精通していない場合は、 Python3でFlaskを使用してWebアプリケーションを作成する方法とPython3でsqlite3モジュールを使用する方法を確認してください。

ステップ1—Webアプリケーションのセットアップ

このステップでは、変更の準備ができたToDoアプリケーションをセットアップします。 また、データベーススキーマを確認して、データベースの構造を理解します。 前提条件セクションのチュートリアルに従い、ローカルマシンにコードと仮想環境が残っている場合は、この手順をスキップできます。

Flask Webアプリケーションに多対多の関係を追加する方法を示すために、前のチュートリアルのアプリケーションコードを使用します。これは、 Flask SQLiteを使用して構築されたToDo管理Webアプリケーションです。 ]、およびブートストラップフレームワーク。 このアプリケーションを使用すると、ユーザーは新しいTo Doを作成したり、既存のTo Doを変更および削除したり、ToDoを完了としてマークしたりできます。

リポジトリのクローンを作成し、名前を flask-todo-2flask_todo 次のコマンドを使用します。

  1. git clone https://github.com/do-community/flask-todo-2 flask_todo

案内する flask_todo:

  1. cd flask_todo

次に、新しい仮想環境を作成します。

  1. python -m venv env

環境をアクティブにします。

  1. source env/bin/activate

Flaskをインストールします:

  1. pip install Flask

次に、を使用してデータベースを初期化します。 init_db.py プログラム:

  1. python init_db.py

次に、次の環境変数を設定します。

  1. export FLASK_APP=app
  2. export FLASK_ENV=development

FLASK_APP 現在開発中のアプリケーションを示します。 app.py この場合。 FLASK_ENV モードを指定します—に設定します development 開発モードの場合。 これにより、アプリケーションをデバッグできます。 (実稼働環境ではこのモードを使用しないでください。)

次に、開発サーバーを実行します。

  1. flask run

ブラウザにアクセスすると、次のURLでアプリケーションが実行されます。 http://127.0.0.1:5000/.

開発サーバーを停止するには、 CTRL + C.

次に、データベーススキーマを調べて、テーブル間の現在の関係を理解します。 内容に精通している方 schema.sql ファイルの場合は、次の手順にスキップできます。

を開きます schema.sql ファイル:

  1. nano schema.sql

ファイルの内容は次のとおりです。

フラスコ_todo/schema.sql
DROP TABLE IF EXISTS lists;
DROP TABLE IF EXISTS items;

CREATE TABLE lists (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    title TEXT NOT NULL
);

CREATE TABLE items (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    list_id INTEGER NOT NULL,
    created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    content TEXT NOT NULL,
    done INTEGER NOT NULL DEFAULT 0,
    FOREIGN KEY (list_id) REFERENCES lists (id)
);

の中に schema.sql ファイルには、2つのテーブルがあります。 lists リストを保存するため(など Home また Study)、 と items ToDoアイテム(など)を保存するため Do the dishes また Learn Flask).

The lists テーブルには次の列があります。

  • id:リストのID。
  • created:リストの作成日。
  • title:リストのタイトル。

The items テーブルには次の列があります。

  • id:アイテムのID。
  • list_id:アイテムが属するリストのID。
  • created:アイテムの作成日。
  • content:アイテムのコンテンツ。
  • done:アイテムの状態、値 0 アイテムがまだ完了していないことを示しますが、 1 アイテムの完了を示します。

の中に items 外部キー制約があるテーブル。 list_id 列は id の列 lists 親テーブル。 これは、アイテムとリストの間の1対多の関係であり、リストに複数のアイテムを含めることができ、アイテムが1つのリストに属していることを示します。

FOREIGN KEY (list_id) REFERENCES lists (id)

次のステップでは、多対多の関係を使用して、2つのテーブル間にリンクを作成します。

ステップ2—担当者テーブルを追加する

このステップでは、多対多の関係と結合テーブルを実装する方法を確認します。 次に、担当者を保存するための新しいテーブルを追加します。

多対多の関係は、テーブル内の各アイテムが他のテーブル内の多くの関連アイテムを持っている2つのテーブルをリンクします。

次のように、やること項目の簡単なテーブルがあるとします。

Items
+----+-------------------+
| id | content           |
+----+-------------------+
| 1  | Buy eggs          |
| 2  | Fix lighting      |
| 3  | Paint the bedroom |
+----+-------------------+

そして、そのような譲受人のための表:

assignees
+----+------+
| id | name |
+----+------+
| 1  | Sammy|
| 2  | Jo   |
+----+------+

やることを割り当てたいとしましょう Fix lighting 両方へ SammyJo、これを行うには、に新しい行を追加します items そのようなテーブル:

items
+----+-------------------+-----------+
| id | content           | assignees |
+----+-------------------+-----------+
| 1  | Buy eggs          |           |
| 2  | Fix lighting      | 1, 2      |
| 3  | Paint the bedroom |           |
+----+-------------------+-----------+

各列には1つの値しかないため、これは間違ったアプローチです。 複数の値がある場合、データの追加や更新などの基本的な操作は面倒で時間がかかります。 代わりに、関連するテーブルの主キーを参照する3番目のテーブルが必要です。このテーブルは結合テーブルと呼ばれることが多く、各テーブルの各アイテムのIDを格納します。

アイテムと担当者をリンクする結合テーブルの例を次に示します。

item_assignees
+----+---------+-------------+
| id | item_id | assignee_id |
+----+---------+-------------+
| 1  | 2       | 1           |
| 2  | 2       | 2           |
+----+---------+-------------+

最初の行で、IDを持つアイテム 2 (あれは、 Fix lighting)IDを持つ譲受人に関連する 1 (Sammy). 2行目では、同じ項目がIDを持つ譲受人にも関連しています 2 (Jo). これは、やること項目が両方に割り当てられることを意味します SammyJo. 同様に、各担当者を複数のアイテムに割り当てることができます。

次に、To Doアプリケーションのデータベースを変更して、担当者を格納するためのテーブルを追加します。

まず、開く schema.sql 名前の付いた新しいテーブルを追加するには assignees:

  1. nano schema.sql

行を追加して削除します assignees すでに存在する場合はテーブル。 これは、既存のデータベースなど、データベースを再起動するときに発生する可能性のある将来の問題を回避するためです。 assignees 異なる列を持つテーブル。同じスキーマに従わない場合、コードが予期せず破損する可能性があります。 テーブルのSQLコードも追加します。

フラスコ_todo/schema.sql
DROP TABLE IF EXISTS assignees;
DROP TABLE IF EXISTS lists;
DROP TABLE IF EXISTS items;

CREATE TABLE lists (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    title TEXT NOT NULL
);

CREATE TABLE items (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    list_id INTEGER NOT NULL,
    created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    content TEXT NOT NULL,
    done INTEGER NOT NULL DEFAULT 0,
    FOREIGN KEY (list_id) REFERENCES lists (id)
);

CREATE TABLE assignees (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL
);

ファイルを保存して閉じます。

この新しい assignees テーブルには次の列があります。

  • id:譲受人のID。
  • name:譲受人の名前。

編集します init_db.py データベースに数人の担当者を追加するプログラム。 このプログラムを使用して、データベースを初期化します。

  1. nano init_db.py

次のようにファイルを変更します。

フラスコ_todo/init_db.py
import sqlite3

connection = sqlite3.connect('database.db')

with open('schema.sql') as f:
    connection.executescript(f.read())

cur = connection.cursor()

cur.execute("INSERT INTO lists (title) VALUES (?)", ('Work',))
cur.execute("INSERT INTO lists (title) VALUES (?)", ('Home',))
cur.execute("INSERT INTO lists (title) VALUES (?)", ('Study',))

cur.execute("INSERT INTO items (list_id, content) VALUES (?, ?)",
            (1, 'Morning meeting')
            )

cur.execute("INSERT INTO items (list_id, content) VALUES (?, ?)",
            (2, 'Buy fruit')
            )

cur.execute("INSERT INTO items (list_id, content) VALUES (?, ?)",
            (2, 'Cook dinner')
            )

cur.execute("INSERT INTO items (list_id, content) VALUES (?, ?)",
            (3, 'Learn Flask')
            )

cur.execute("INSERT INTO items (list_id, content) VALUES (?, ?)",
            (3, 'Learn SQLite')
            )

cur.execute("INSERT INTO assignees (name) VALUES (?)", ('Sammy',))
cur.execute("INSERT INTO assignees (name) VALUES (?)", ('Jo',))
cur.execute("INSERT INTO assignees (name) VALUES (?)", ('Charlie',))
cur.execute("INSERT INTO assignees (name) VALUES (?)", ('Ashley',))

connection.commit()
connection.close()

ファイルを保存して閉じます。

強調表示された行で、カーソルオブジェクトを使用して INSERT 4つの名前をに挿入するSQLステートメント assignees テーブル。 あなたは ? execute()メソッドのプレースホルダーを指定し、担当者の名前を含むタプルを渡して、データベースにデータを安全に挿入します。 次に、でトランザクションをコミットします connection.commit() を使用して接続を閉じます connection.close().

これにより、4人の担当者がデータベースに追加されます。 Sammy, Jo, Charlie、 と Ashley.

を実行します init_db.py データベースを再初期化するプログラム:

  1. python init_db.py

これで、担当者をデータベースに保存するためのテーブルができました。 次に、結合テーブルを追加して、アイテムと担当者の間に多対多の関係を作成します。

ステップ3—多対多の結合テーブルを追加する

このステップでは、結合テーブルを使用して、ToDoアイテムを担当者にリンクします。 まず、データベーススキーマファイルを編集して新しい結合テーブルを追加し、データベース初期化プログラムを編集していくつかの割り当てを追加し、次にデモプログラムを使用して各ToDoの担当者を表示します。

開ける schema.sql 新しいテーブルを追加するには:

  1. nano schema.sql

テーブルはアイテムと担当者を結合するため、これを呼び出します item_assignees. テーブルがすでに存在する場合は削除する行を追加してから、テーブル自体のSQLコードを追加します。

フラスコ_todo/schema.sql
DROP TABLE IF EXISTS assignees;
DROP TABLE IF EXISTS lists;
DROP TABLE IF EXISTS items;
DROP TABLE IF EXISTS item_assignees;


CREATE TABLE lists (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    title TEXT NOT NULL
);

CREATE TABLE items (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    list_id INTEGER NOT NULL,
    created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
    content TEXT NOT NULL,
    done INTEGER NOT NULL DEFAULT 0,
    FOREIGN KEY (list_id) REFERENCES lists (id)
);

CREATE TABLE assignees (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL
);

CREATE TABLE item_assignees (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    item_id INTEGER,
    assignee_id INTEGER,
    FOREIGN KEY(item_id) REFERENCES items(id),
    FOREIGN KEY(assignee_id) REFERENCES assignees(id)
);

ファイルを保存して閉じます。

この新しい item_assignees テーブルには次の列があります。

  • id:やることと譲受人の間の関係を確立するエントリのID。 各行は関係を表します。
  • item_id:対応する担当者に割り当てられるToDoアイテムのID assignee_id.
  • assignee_id:対応するアイテムが割り当てられる担当者のID item_id.

The item_assignees テーブルには2つの外部キー制約もあります。1つは item_id の列 id の列 items テーブル、および assignee_id の列 id の列 assignees テーブル。

開ける init_db.py いくつかの割り当てを追加するには:

  1. nano init_db.py

次のようにファイルを変更します。

フラスコ_todo/init_db.py
import sqlite3

connection = sqlite3.connect('database.db')


with open('schema.sql') as f:
    connection.executescript(f.read())

cur = connection.cursor()

cur.execute("INSERT INTO lists (title) VALUES (?)", ('Work',))
cur.execute("INSERT INTO lists (title) VALUES (?)", ('Home',))
cur.execute("INSERT INTO lists (title) VALUES (?)", ('Study',))

cur.execute("INSERT INTO items (list_id, content) VALUES (?, ?)",
            (1, 'Morning meeting')
            )

cur.execute("INSERT INTO items (list_id, content) VALUES (?, ?)",
            (2, 'Buy fruit')
            )

cur.execute("INSERT INTO items (list_id, content) VALUES (?, ?)",
            (2, 'Cook dinner')
            )

cur.execute("INSERT INTO items (list_id, content) VALUES (?, ?)",
            (3, 'Learn Flask')
            )

cur.execute("INSERT INTO items (list_id, content) VALUES (?, ?)",
            (3, 'Learn SQLite')
            )

cur.execute("INSERT INTO assignees (name) VALUES (?)", ('Sammy',))
cur.execute("INSERT INTO assignees (name) VALUES (?)", ('Jo',))
cur.execute("INSERT INTO assignees (name) VALUES (?)", ('Charlie',))
cur.execute("INSERT INTO assignees (name) VALUES (?)", ('Ashley',))

# Assign "Morning meeting" to "Sammy"
cur.execute("INSERT INTO item_assignees (item_id, assignee_id) VALUES (?, ?)",
            (1, 1))

# Assign "Morning meeting" to "Jo"
cur.execute("INSERT INTO item_assignees (item_id, assignee_id) VALUES (?, ?)",
            (1, 2))

# Assign "Morning meeting" to "Ashley"
cur.execute("INSERT INTO item_assignees (item_id, assignee_id) VALUES (?, ?)",
            (1, 4))

# Assign "Buy fruit" to "Sammy"
cur.execute("INSERT INTO item_assignees (item_id, assignee_id) VALUES (?, ?)",
            (2, 1))

connection.commit()
connection.close()

強調表示されたコードでは、に挿入することにより、ToDo項目を担当者に割り当てます。 item_assignees テーブルに参加します。 挿入します item_id に対応するIDを持つ譲受人に割り当てたいやること項目の assignee_id 価値。 最初に強調表示されている行で、やること項目を割り当てます Morning meeting、IDは 1、譲受人へ Sammy、IDを持っている人 1. 残りの行は同じパターンに従います。 もう一度、あなたは ? タプルに挿入する値を安全に渡すためのプレースホルダー cur.execute() 方法。

ファイルを保存して閉じます。

を実行します init_db.py データベースを再初期化するプログラム:

  1. python init_db.py

を実行します list_example.py データベースにあるToDo項目を表示するプログラム:

  1. python list_example.py

出力は次のとおりです。

Output
Home Buy fruit | id: 2 | done: 0 Cook dinner | id: 3 | done: 0 Study Learn Flask | id: 4 | done: 0 Learn SQLite | id: 5 | done: 0 Work Morning meeting | id: 1 | done: 0

これにより、ToDo項目が属するリストの下に表示されます。 各アイテムのコンテンツ、ID、および完了したかどうかがわかります(0 アイテムがまだ完成していないことを意味し、 1 完了したことを意味します)。 次に、各ToDoの担当者を表示する必要があります。

開ける list_example.py アイテムの担当者を表示するように変更するには:

  1. nano list_example.py

次のようにファイルを変更します。

フラスコ_todo/list_example.py
from itertools import groupby
from app import get_db_connection

conn = get_db_connection()
todos = conn.execute('SELECT i.id, i.done, i.content, l.title \
                      FROM items i JOIN lists l \
                      ON i.list_id = l.id ORDER BY l.title;').fetchall()

lists = {}

for k, g in groupby(todos, key=lambda t: t['title']):
    # Create an empty list for items
    items = []
    # Go through each to-do item row in the groupby() grouper object
    for item in g:
        # Get the assignees of the current to-do item
        assignees = conn.execute('SELECT a.id, a.name FROM assignees a \
                                  JOIN item_assignees i_a \
                                  ON a.id = i_a.assignee_id \
                                  WHERE i_a.item_id = ?',
                                  (item['id'],)).fetchall()
        # Convert the item row into a dictionary to add assignees
        item = dict(item)
        item['assignees'] = assignees

        items.append(item)

    # Build the list of dictionaries
    # the list's name (ex: Home/Study/Work) as the key

    # and a list of dictionaries of to-do items
    # belonging to that list as the value
    lists[k] = list(items)


for list_, items in lists.items():
    print(list_)
    for item in items:
        assignee_names = ', '.join(a['name'] for a in item['assignees'])

        print('    ', item['content'], '| id:',
              item['id'], '| done:', item['done'],
              '| assignees:', assignee_names)

ファイルを保存して閉じます。

groupby()関数を使用して、ToDoアイテムをそれらが属するリストのタイトルでグループ化します。 (詳細については、FlaskおよびSQLiteで1対多のデータベース関係を使用する方法のステップ2を参照してください。)グループ化プロセスの実行中に、次のような空のリストを作成します。 items、アイテムのID、コンテンツ、担当者など、すべてのToDoアイテムデータを保持します。 次に、 for item in g ループ、各To Doアイテムを確認し、アイテムの担当者を取得して、 assignees 変数。

The assignees 変数は、 SELECT SQLクエリ。 このクエリは、担当者のIDを取得します(a.id)および譲受人の名前(a.name) から assignees テーブル(エイリアスは a クエリを短縮します)。 クエリはIDと名前を item_assignees テーブルに参加(別名 i_a)条件付き a.id = i_a.assignee_id どこ i_a.item_id 値は現在のアイテムのIDの値と同じです(item['id']). 次に、 fetchall()メソッドを使用して、結果をリストとして取得します。

ラインで item = dict(item)、通常の sqlite3.Row オブジェクトは割り当てをサポートしていないため、アイテムを辞書に変換します。割り当ては、アイテムに担当者を追加する必要があります。 次に、ラインで item['assignees'] = assignees、新しいキーを追加します 'assignees'item アイテムの辞書から直接アイテムの担当者にアクセスするための辞書。 次に、変更したアイテムをに追加します items リスト。 すべてのデータを保持する辞書のリストを作成します。 各辞書キーはやることリストのタイトルであり、その値はそれに属するすべての項目のリストです。

結果を印刷するには、 for list_, items in lists.items() 各ToDoリストのタイトルとそれに属するToDoアイテムを確認するためにループし、リストのタイトルを印刷します(list_)次に、リストのToDo項目をループします。 名前の付いた変数を追加しました assignee_names、その値は join()メソッドを使用して、ジェネレーター式の項目間を結合します。 a['name'] for a in item['assignees']、譲受人の名前を抽出します(a['name'])、の各譲受人のデータから item['assignees'] リスト。 この結合された担当者名のリストを使用して、ToDoアイテムの残りのデータを印刷します。 print() 関数。

を実行します list_example.py プログラム:

  1. python list_example.py

出力は次のとおりです(担当者が強調表示されています)。

Output
Home Buy fruit | id: 2 | done: 0 | assignees: Sammy Cook dinner | id: 3 | done: 0 | assignees: Study Learn Flask | id: 4 | done: 0 | assignees: Learn SQLite | id: 5 | done: 0 | assignees: Work Morning meeting | id: 1 | done: 0 | assignees: Sammy, Jo, Ashley

これで、各ToDo項目の担当者を残りのデータとともに表示できます。

これで、各ToDo項目の担当者名が表示されました。 次に、これを使用して、Webアプリケーションのインデックスページの各ToDo項目の下に名前を表示します。

ステップ4—インデックスページに担当者を表示する

このステップでは、To Do管理アプリケーションのインデックスページを変更して、各ToDo項目の担当者を表示します。 最初に編集します app.py Flaskアプリケーションのコードを含むファイルを作成し、 index.html インデックスページの各ToDo項目の下に担当者を表示するためのテンプレートファイル。

まず、開く app.py 編集するには index() ビュー機能:

  1. nano app.py

次のように関数を変更します。

フラスコ_todo/app.py
@app.route('/')
def index():
    conn = get_db_connection()
    todos = conn.execute('SELECT i.id, i.done, i.content, l.title \
                          FROM items i JOIN lists l \
                          ON i.list_id = l.id ORDER BY l.title;').fetchall()

    lists = {}

    for k, g in groupby(todos, key=lambda t: t['title']):
        # Create an empty list for items
        items = []
        # Go through each to-do item row in the groupby() grouper object
        for item in g:
            # Get the assignees of the current to-do item
            assignees = conn.execute('SELECT a.id, a.name FROM assignees a \
                                    JOIN item_assignees i_a \
                                    ON a.id = i_a.assignee_id \
                                    WHERE i_a.item_id = ?',
                                    (item['id'],)).fetchall()
            # Convert the item row into a dictionary to add assignees
            item = dict(item)
            item['assignees'] = assignees

            items.append(item)

        # Build the list of dictionaries
        # the list's name (ex: Home/Study/Work) as the key

        # and a list of dictionaries of to-do items
        # belonging to that list as the value
        lists[k] = list(items)

    conn.close()
    return render_template('index.html', lists=lists)

ファイルを保存して閉じます。

これは、で使用したのと同じコードです。 list_example.py ステップ3のデモプログラム。 これで、 lists 変数には、担当者データを含む、必要なすべてのデータが含まれます。これを使用して、 index.html テンプレートファイル。

を開きます index.html 各項目の後に担当者名を追加するファイル:

  1. nano templates/index.html

次のようにファイルを変更します。

フラスコ_todo/templates / index.html
{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Welcome to FlaskTodo {% endblock %}</h1>
    {% for list, items in lists.items() %}
        <div class="card" style="width: 18rem; margin-bottom: 50px;">
            <div class="card-header">
                <h3>{{ list }}</h3>
            </div>
            <ul class="list-group list-group-flush">
                {% for item in items %}
                    <li class="list-group-item"
                    {% if item['done'] %}
                    style="text-decoration: line-through;"
                    {% endif %}
                    >{{ item['content'] }}
                    {% if not item ['done'] %}
                        {% set URL = 'do' %}
                        {% set BUTTON = 'Do' %}
                    {% else %}
                        {% set URL = 'undo' %}
                        {% set BUTTON = 'Undo' %}
                    {% endif %}
                    <div class="row">
                        <div class="col-12 col-md-3">
                            <form action="{{ url_for(URL, id=item['id']) }}"
                                method="POST">
                                <input type="submit" value="{{ BUTTON }}"
                                    class="btn btn-success btn-sm">
                            </form>
                        </div>

                        <div class="col-12 col-md-3">
                            <a class="btn btn-warning btn-sm"
                            href="{{ url_for('edit', id=item['id']) }}">Edit</a>
                        </div>

                        <div class="col-12 col-md-3">
                            <form action="{{ url_for('delete', id=item['id']) }}"
                                method="POST">
                                <input type="submit" value="Delete"
                                    class="btn btn-danger btn-sm">
                            </form>
                        </div>
                    </div>

                    <hr>
                    {% if item['assignees'] %}
                        <span style="color: #6a6a6a">Assigned to</span>
                        {% for assignee in item['assignees'] %}
                            <span class="badge badge-primary">
                                {{ assignee['name'] }}
                            </span>
                        {% endfor %}
                    {% endif %}

                    </li>
                {% endfor %}
            </ul>
        </div>
    {% endfor %}
{% endblock %}

ファイルを保存して閉じます。

この変更により、各アイテムの下に改行を追加しました。 <hr> 鬼ごっこ。 アイテムに譲受人がいる場合(ステートメントでわかります) if item['assignees'])、灰色を表示します Assigned to テキストを送信し、アイテムの担当者をループします(つまり、 item['assignees'] リスト)、および担当者名を表示します(assignee['name']バッジ内。

最後に、開発サーバーを実行します。

  1. flask run

次に、インデックスページにアクセスします。 http://127.0.0.1:5000/.

各ToDoアイテムに多数の担当者を含めることができるようになり、各担当者に複数のToDoを割り当てることができます。 インデックスページには、すべてのアイテムと各アイテムの担当者が表示されます。

このリポジトリから最終コードにアクセスできます。

結論

このチュートリアルでは、多対多の関係とは何か、FlaskおよびSQLite Webアプリケーションでの使用方法、テーブル間の結合方法、Pythonでのリレーショナルデータのグループ化方法について学習しました。

これで、ユーザーが新しいTo Doアイテムを作成し、アイテムを完了としてマークし、既存のアイテムを編集または削除し、新しいリストを作成できる完全なToDoアプリケーションができました。 また、各アイテムを異なる担当者に割り当てることができます。

PythonとFlaskを使用したWeb開発の詳細については、これらのFlaskチュートリアルを参照してください。