著者は、Free and Open Source Fundを、Write for DOnationsプログラムの一環として寄付先として選択しました。
導入
Webアプリケーションでは、通常、データベースが必要です。これはデータの整理されたコレクションです。データベースを使用して、取得および効率的に操作できる永続データを保存および維持します。例えば、ソーシャルメディアアプリケーションでは、ユーザーデータ(個人情報、投稿、コメント、フォロワーなど)が効率的に操作できるように保存されているデータベースがあります。データベースにデータを追加したり、取得したり、変更したり、削除したりすることができますが、これは異なる要件や条件に応じて行います。Webアプリケーションでは、これらの要件が、ユーザーが新しい投稿を追加したり、投稿を削除したり、アカウントを削除したりする場合になります。これらのデータを操作するためのアクションは、アプリケーションの特定の機能に依存します。たとえば、ユーザーがタイトルのない投稿を追加することを許可したくない場合があります。
DigitalOcean App Platformを使用してGitHubからFlaskアプリケーションをデプロイします。DigitalOceanにアプリのスケーリングを任せましょう。
Flaskは、Python言語でウェブアプリケーションを作成するための便利なツールや機能を提供する軽量なPythonウェブフレームワークです。SQLAlchemyは、リレーショナルデータベースに効率的で高性能なデータベースアクセスを提供するSQLツールキットです。SQLite、MySQL、およびPostgreSQLなどの複数のデータベースエンジンとやり取りする方法を提供します。データベースのSQL機能にアクセスできます。また、Object Relational Mapper(ORM)を提供し、簡単なPythonオブジェクトとメソッドを使用してクエリを作成し、データを処理できます。Flask-SQLAlchemyは、FlaskとSQLAlchemyを簡単に使用できるようにするFlask拡張機能であり、Flaskアプリケーション内でSQLAlchemyを使用してデータベースとやり取りするためのツールやメソッドを提供します。
このチュートリアルでは、Flask-SQLAlchemy拡張機能の使用方法を示す小さな学生管理システムを構築します。 Flaskと組み合わせて、データベースサーバーに接続したり、テーブルを作成したり、テーブルにデータを追加したり、データを取得したり、データベースから項目を更新したり削除したりするなど、基本的なタスクを実行します。 SQLiteを使用してSQLAlchemyを使用しますが、PostgreSQLやMySQLなどの他のデータベースエンジンでも使用できます。Python標準ライブラリには、何もインストールせずにSQLAlchemyがSQLiteデータベースとやり取りするために背後で使用されるsqlite3
モジュールが提供されているため、Pythonとよく動作します。 SQliteはLinuxシステムにデフォルトでインストールされており、WindowsではPythonパッケージの一部としてインストールされています。
前提条件
-
ローカルのPython 3プログラミング環境。 Python 3のローカルプログラミング環境のインストールとセットアップ シリーズのチュートリアルに従ってください。このチュートリアルでは、プロジェクトディレクトリを
flask_app
と呼びます。 -
ルート、ビュー関数、テンプレートなどの基本的なFlaskの概念の理解。Flaskに慣れていない場合は、FlaskとPythonを使用した最初のWebアプリケーションの作成方法 と Flaskアプリケーションでテンプレートを使用する方法 をチェックしてください。
-
基本的なHTMLの概念の理解。バックグラウンド知識については、弊社のHTMLでウェブサイトを構築する方法
チュートリアルシリーズを参照してください。
ステップ1 — FlaskとFlask-SQLAlchemyのインストール
このステップでは、アプリケーションに必要なパッケージをインストールします。
仮想環境がアクティブになっている場合は、pip
を使用してFlaskとFlask-SQLAlchemyをインストールします:
インストールが正常に完了すると、出力の最後に次のような行が表示されます:
OutputSuccessfully installed Flask-2.0.3 Flask-SQLAlchemy-2.5.1 Jinja2-3.0.3 MarkupSafe-2.1.0 SQLAlchemy-1.4.31 Werkzeug-2.0.3 click-8.0.4 greenlet-1.1.2 itsdangerous-2.1.0
必要なPythonパッケージがインストールされたら、次にデータベースを設定します。
ステップ2 — データベースとモデルの設定
このステップでは、データベース接続を設定し、データを格納するテーブルを表すPythonクラスであるSQLAlchemy データベースモデルを作成します。データベースを初期化し、宣言したモデルに基づいて学生用のテーブルを作成し、いくつかの学生を学生テーブルに追加します。
データベース接続の設定
「flask_app」ディレクトリ内のapp.py
という名前のファイルを開きます。このファイルには、データベースの設定とFlaskのルートのコードが含まれます。
このファイルは、database.db
という名前のSQLiteデータベースに接続し、学生情報を格納するためのデータベース学生テーブルを表すStudent
というクラスを持ち、Flaskのルートも含みます。次のimport
文をapp.py
の先頭に追加します:
ここで、os
モジュールをインポートしています。これにより、database.db
データベースファイルのファイルパスを構築できます。
flask
パッケージから、アプリケーションで必要なヘルパーをインポートします:Flaskアプリケーションインスタンスを作成するためのFlask
クラス、テンプレートをレンダリングするためのrender_template()
関数、リクエストを処理するためのrequest
オブジェクト、ルート用のURLを構築するためのurl_for()
関数、およびユーザーをリダイレクトするためのredirect()
関数。ルートとテンプレートの詳細については、Flaskアプリケーションでテンプレートを使用する方法を参照してください。
次に、Flask-SQLAlchemy拡張からSQLAlchemy
クラスをインポートし、これにより、SQLAlchemyのすべての関数やクラスにアクセスできるようになります。FlaskをSQLAlchemyと統合するためのヘルパーや機能に加えて、SQLAlchemyの機能も利用できます。これを使用して、Flaskアプリケーションに接続するデータベースオブジェクトを作成し、Pythonのクラス、オブジェクト、および関数を使用してテーブルを作成および操作することができます。SQL言語を使用せずに。
さらに、sqlalchemy.sql
モジュールからfunc
ヘルパーをインポートしてSQL関数にアクセスします。これは、学生管理システムで、学生レコードが作成されたときのデフォルトの作成日時を設定するために必要です。
インポートの下に、データベースファイルのパスを設定し、Flaskアプリケーションをインスタンス化し、アプリケーションをSQLAlchemyと構成して接続します。次のコードを追加します:
ここでは、SQLiteデータベースファイルのパスを構築します。まず、ベースディレクトリを現在のディレクトリとして定義します。os.path.abspath()
関数を使用して、現在のファイルのディレクトリの絶対パスを取得します。特別な__file__
変数は、現在のapp.py
ファイルのパス名を保持します。ベースディレクトリの絶対パスをbasedir
という変数に保存します。
次に、app
というFlaskアプリケーションインスタンスを作成し、それを使用して2つのFlask-SQLAlchemy 設定キーを構成します。
-
SQLALCHEMY_DATABASE_URI
:データベースとの接続を確立するためのデータベースURI。この場合、URIはsqlite:///path/to/database.db
の形式に従います。basedir
変数に構築して保存したベースディレクトリとdatabase.db
ファイル名をos.path.join()
関数を使用してスマートに結合します。これにより、flask_app
ディレクトリ内のdatabase.db
データベースファイルに接続されます。データベースは初期化するとファイルが作成されます。 -
SQLALCHEMY_TRACK_MODIFICATIONS
:オブジェクトの変更を追跡するかどうかを設定する構成です。メモリを節約するためにFalse
に設定します。詳細については、Flask-SQLAlchemyドキュメントの構成ページを参照してください。
注意:
PostgreSQLやMySQLなどの他のデータベースエンジンを使用する場合は、適切なURIを使用する必要があります。
PostgreSQLの場合、以下の形式を使用します:
postgresql://username:password@host:port/database_name
MySQLの場合:
mysql://username:password@host:port/database_name
さらに詳しくは、SQLAlchemyのエンジン構成に関するドキュメントを参照してください。
SQLAlchemyを設定してデータベースURIを設定し、トラッキングを無効にした後、SQLAlchemy
クラスを使用してデータベースオブジェクトを作成し、FlaskアプリケーションをSQLAlchemyで接続するためにアプリケーションインスタンスを渡します。データベースオブジェクトをdb
という変数に格納します。このdb
オブジェクトを使用してデータベースとやり取りします。
テーブルの宣言
データベース接続が確立され、データベースオブジェクトが作成されたので、データベースオブジェクトを使用して、学生用のデータベーステーブルを作成します。これはモデルであり、Flask-SQLAlchemyが提供するベースクラスから継承するPythonクラスです。以前に作成したdb
データベースインスタンスを介して提供されます。モデルとして学生テーブルを定義するには、次のクラスをapp.py
ファイルに追加します:
ここでは、Student
モデルを作成し、db.Model
クラスから継承します。これは学生テーブルを表します。テーブルの列を定義するためにdb.Column
クラスを使用します。最初の引数は列の型を表し、追加の引数は列の構成を表します。
Student
モデルには、以下の列を定義します:
id
:学生のID。これをdb.Integer
で整数として定義します。primary_key=True
はこの列を 主キー として定義し、データベースがそれぞれのエントリ(つまり学生)に対して一意の値を割り当てます。firstname
:学生の名。最大長100
文字の文字列です。nullable=False
はこの列が空にならないことを示します。lastname
:学生の姓。最大長100
文字の文字列です。nullable=False
はこの列が空にならないことを示します。email
:学生のメールアドレス。最大長80
文字の文字列です。unique=True
は各学生のメールアドレスが一意であることを示します。nullable=False
はこの列が空にならないことを示します。age
:学生の年齢。created_at
:データベース内で学生の記録が作成された時刻です。Pythonのdb.DateTime
を使用して、これをdatetime
オブジェクトとして定義します。timezone=True
はタイムゾーンのサポートを有効にします。server_default
は、テーブルを作成するときにデータベースにデフォルト値を設定し、デフォルト値をモデルではなくデータベースで処理するようにします。func.now()
関数を渡します。これはSQLのnow()
datetime関数を呼び出します。 SQLiteでは、学生テーブルを作成するときにCURRENT_TIMESTAMP
としてレンダリングされます。bio
:学生のバイオです。db.Text()
は列が長いテキストを保持することを示します。
前のコードブロックで使用したタイプ以外の列タイプについては、SQLAlchemyのドキュメントを参照してください。
特別な__repr__
関数を使用すると、各オブジェクトにデバッグ目的で認識できる文字列表現を付与できます。 この場合、学生の名前を使用します。
app.py
ファイルは以下のようになります:
app.py
を保存して閉じます。
データベースの作成
データベース接続と学生モデルを設定したので、Flaskシェルを使用してデータベースと学生テーブルを作成します。 Student
モデルに基づいています。
仮想環境がアクティブ化されている場合は、app.py
ファイルをFlaskアプリケーションとして設定し、FLASK_APP
環境変数を使用します。 次に、flask_app
ディレクトリで以下のコマンドを使用してFlaskシェルを開きます:
A Python interactive shell will be opened. This special shell runs commands in the context of your Flask application, so that the Flask-SQLAlchemy functions you’ll call are connected to your application.
データベースオブジェクトと学生モデルをインポートし、db.create_all()
関数を実行して、モデルに関連付けられたテーブルを作成します。 この場合、1つのモデルしかないため、関数呼び出しはデータベースに1つのテーブルのみを作成します:
シェルを実行したままにして、別のターミナルウィンドウを開き、flask_app
ディレクトリに移動します。 これで、flask_app
に新しいファイルdatabase.db
が表示されます。
注意:
db.create_all()
関数は、テーブルがすでに存在する場合には再作成または更新しません。たとえば、モデルを変更して新しい列を追加した場合、db.create_all()
関数を実行しても、データベースにすでにテーブルが存在する場合はモデルへの変更が適用されません。解決策は、db.drop_all()
関数を使用してすべての既存のデータベーステーブルを削除し、db.create_all()
関数を使用して再作成することです。
これにより、モデルに加えた変更が適用されますが、データベース内のすべての既存データも削除されます。データベースを更新して既存のデータを保持するには、スキーママイグレーションを使用する必要があります。これにより、テーブルを変更してデータを保持できます。
エラーが発生した場合は、データベースURIとモデルの宣言が正しいことを確認してください。
テーブルの追加
データベースと学生テーブルを作成した後、Student
モデルを介してデータベースにいくつかの学生を追加します。
以前に開いた同じflaskシェルを使用するか、flask_app
ディレクトリで仮想環境を有効にして新しいシェルを開きます。
データベースに学生を追加するには、データベースオブジェクトとStudent
モデルをインポートし、Student
モデルのインスタンスを作成します。キーワード引数を介して学生データを渡します。
student_john
オブジェクトは、データベースに追加される学生を表しますが、このオブジェクトはまだデータベースに書かれていません。作成した表現文字列を flask シェルで確認するには、__repr__()
メソッドを使用してください。
以下の出力が表示されます。
Output<Student john>
定義したStudent
モデルのクラス属性を使用して、列の値を取得できます。
Output'john'
'Biology student'
この学生がまだデータベースに追加されていないため、その ID はNone
になります。
OutputNone
この学生をデータベースに追加するには、まずデータベースのトランザクションを管理するデータベースセッションに追加する必要があります。Flask-SQLAlchemy は、db.session
オブジェクトを提供しており、このオブジェクトを使用してデータベースの変更を管理できます。セッションにstudent_john
オブジェクトを追加するには、db.session.add()
メソッドを使用してください。
これによりINSERT
ステートメントが発行されますが、データベーストランザクションはまだコミットされていないため、ID は返されません。トランザクションをコミットし、変更をデータベースに適用するには、db.session.commit()
メソッドを使用してください。
これで、学生 John がデータベースに追加されたので、その ID を取得できます。
Output1
また、db.session.add()
メソッドを使用してデータベース内のアイテムを編集することもできます。たとえば、次のように学生のメールアドレスを変更できます:
Flaskシェルを使用して、データベースにさらにいくつかの学生を追加します:
今、all()
メソッドを使用してquery
属性で学生テーブルのすべてのレコードをクエリできます:
以下の出力が表示されます:
Output[<Student john>, <Student Sammy>, <Student Carl>]
この時点で、データベースに3人の学生がいます。次に、インデックスページ用のFlaskルートを作成し、データベースのすべての学生をそのページに表示します。
ステップ3 — レコードのすべてを表示する
このステップでは、データベースのすべての学生をインデックスページで表示するためのルートとテンプレートを作成します。
Flaskシェルを実行したままにして、新しいターミナルウィンドウを開きます。
app.py
ファイルを開いて、それにインデックスページのためのルートを追加します:
ファイルの末尾に次のルートを追加してください:
ファイルを保存して閉じます。
ここでは、app.route()
デコレータを使用してindex()
ビュー関数を作成します。この関数では、query
属性を使用してStudent
モデルを使用してデータベースをクエリし、さまざまなメソッドを使用してデータベースから1つ以上のアイテムを取得します。すべての学生エントリをデータベースから取得するためにall()
メソッドを使用します。クエリの結果はstudents
という変数に格納し、render_template()
ヘルパー関数を使用してレンダリングするindex.html
という名前のテンプレートに渡します。
index.html
テンプレートファイルを作成する前に、データベース内の既存の学生を表示するために使用する基本テンプレートを最初に作成します。これにより、コードの繰り返しを避けるために他のテンプレートも使用するすべての基本HTMLコードが含まれます。その後、index()
関数でレンダリングしたindex.html
テンプレートファイルを作成します。テンプレートについて詳しくは、Flaskアプリケーションでテンプレートを使用する方法を参照してください。
templates
ディレクトリを作成し、次にbase.html
という新しいテンプレートを開きます:
次のコードをbase.html
ファイルに追加します:
ファイルを保存して閉じます。
このベーステンプレートには、他のテンプレートで再利用するために必要なすべてのHTMLボイラープレートが含まれています。title
ブロックは各ページのタイトルを設定するために置換され、content
ブロックは各ページのコンテンツで置換されます。ナビゲーションバーには3つのリンクがあります: インデックスページへのリンクは、url_for()
ヘルパー関数を使用してindex()
ビュー関数にリンクします。もう1つはCreateページ用で、もう1つはアプリケーションに追加することを選択した場合のAboutページ用です。後で新しい学生を作成するためのページを追加した後に、このファイルを編集します。
次に、新しいindex.html
テンプレートファイルを開きます。これはapp.py
ファイルで参照されているテンプレートです:
次のコードを追加します:
ファイルを保存して閉じます。
ここでは、ベーステンプレートを拡張してコンテンツブロックの内容を置換します。タイトルとして機能する<h1>
見出しを使用します。 students
変数をこのテンプレートに渡すindex()
ビュー関数から各学生を通過するためのJinja for
ループを使用します。学生のID、名前、メール、年齢、データベースに追加された日付、およびバイオを表示します。
flask_app
ディレクトリ内で仮想環境をアクティブにした状態で、アプリケーション(この場合はapp.py
)についてFlaskに知らせるために、FLASK_APP
環境変数を使用します。次に、アプリケーションを開発モードで実行し、デバッガにアクセスします。Flaskデバッガの詳細については、Flaskアプリケーションでエラーを処理する方法を参照してください。これを行うためには、次のコマンドを使用します:
次に、アプリケーションを実行します:
開発サーバーが実行されている状態で、ブラウザを使用して次のURLにアクセスしてください:
http://127.0.0.1:5000/
データベースに追加した学生が含まれたページが表示されます。ページは次のようなものになります:
データベースに登録されている学生をインデックスページに表示しました。次に、各個人の学生の詳細を表示できる学生ページのルートを作成します。
ステップ4 — 単一のレコードを表示する
このステップでは、Flaskシェルを使用して学生をIDでクエリし、それぞれの学生の詳細を専用ページに表示するためのルートとテンプレートを作成します。
このステップの終了時に、URL http://127.0.0.1:5000/1
は最初の学生を表示するページになります(IDが 1
だからです)。URL http://127.0.0.1:5000/ID
は、関連する ID
番号の投稿を表示します(存在する場合)。
開発サーバーを実行したままにして、新しいターミナルウィンドウを開いてください。
Flaskシェルを開いて、学生をクエリする方法をデモします。
レコードをクエリし、データベースからデータを取得するには、Flask-SQLAlchemyはモデルクラスに query
属性を提供します。そのメソッドを使用して、特定のフィルターでレコードを取得できます。
たとえば、firstname
のような引数を持つ filter_by()
メソッドを使用して、テーブル内の列に一致するパラメータである学生を取得できます:
Output[<Student Sammy>]
ここでは、Sammy
を名前として持つすべての学生を取得します。すべての結果のリストを取得するには、all()
メソッドを使用します。ここでは唯一の結果である最初の結果を取得するには、first()
メソッドを使用できます:
Output<Student Sammy>
ID で学生を取得するには、filter_by(id=ID)
を使用できます:
または、プライマリキーを使用して特定のアイテムを取得できる get()
メソッドを使用できます:
どちらも同じ出力を提供します:
Output<Student Carl>
シェルを終了できます:
学生をIDで取得するには、個々の学生ごとにページをレンダリングする新しいルートを作成します。Flask-SQLAlchemyが提供するget_or_404()
メソッドを使用します。これはget()
メソッドの変種です。違いは、get()
が与えられたIDに一致する結果がない場合に値None
を返し、get_or_404()
が404 Not Found
HTTPレスポンスを返すことです。次のようにapp.py
を修正します:
ファイルの最後に次のルートを追加します:
ファイルを保存して閉じます。
ここでは、'/<int:student_id>/'
というルートを使用します。 int:
は、URL内のデフォルトの文字列を整数に変換するコンバーターであり、student_id
はページに表示する学生を決定するURL変数です。
IDはURLからstudent()
ビュー関数にstudent_id
パラメーター経由で渡されます。関数内で、get_or_404()
メソッドを使用してIDで学生コレクションをクエリし、学生を取得します。データが存在する場合は、学生データをstudent
変数に保存し、データベースに指定されたIDの学生が存在しない場合は404 Not Found
HTTPエラーを返します。
student.html
というテンプレートをレンダリングし、取得した学生を渡します。
この新しいstudent.html
テンプレートファイルを開きます。
以下のコードを新しい student.html
ファイルに入力してください。これは index.html
テンプレートと似ていますが、1人の学生のみを表示します。
ファイルを保存して閉じます。
このファイルでは、ベーステンプレートを拡張し、ページのタイトルとして学生のフルネームを設定します。学生のID、名前、メールアドレス、年齢、レコード作成日、およびバイオを表示します。
ブラウザを使用して、2番目の学生のURLに移動してください。
http://127.0.0.1:5000/2
以下のようなページが表示されます:
次に、index.html
を編集して、それぞれの学生名がそれぞれのページにリンクするようにします。
for
ループを次のように変更します:
ファイルを保存して閉じます。
学生のフルネームに <a>
タグを追加し、url_for()
関数を使用して学生ID(student.id
に保存されている)を student()
ビュー関数に渡します。
インデックスページに移動するか、ページをリフレッシュしてください:
http://127.0.0.1:5000/
今度は、各学生名が正しい学生ページにリンクされていることがわかります。
個々の学生のページを作成した後は、データベースに新しい学生を追加するページを追加します。
ステップ5 — 新しいレコードの作成
このステップでは、Webフォームを使用してデータベースに新しい学生を追加するためのアプリケーションに新しいルートを追加します。
ユーザーが学生のデータを入力するWebフォームを含むページをレンダリングします。その後、フォームの送信を処理し、Student
モデルを使用して新しい学生のオブジェクトを作成し、セッションに追加し、トランザクションをコミットします。ステップ2で学生のエントリを追加した方法と類似しています。
開発サーバーを実行したままで、新しいターミナルウィンドウを開いてください。
まず、app.py
ファイルを開いてください。
app.py
ファイルの末尾に次のルートを追加してください。
ファイルを保存して閉じます。
このルートでは、methods
パラメータにタプル('GET', 'POST')
を渡して、GETリクエストとPOSTリクエストの両方を許可します。GETリクエストはサーバーからデータを取得するために使用されます。POSTリクエストは特定のルートにデータを投稿するために使用されます。デフォルトでは、GETリクエストのみが許可されています。ユーザーが最初にGETリクエストを使用して/create
ルートをリクエストすると、create.html
という名前のテンプレートファイルがレンダリングされます。後で、ユーザーが新しい学生を追加するためのWebフォームを記入して送信する際に、このルートをPOSTリクエストを処理するように編集します。
新しいcreate.html
テンプレートを開いてください。
次のコードを追加してください。
ファイルを保存して閉じます。
ベーステンプレートを拡張し、見出しをタイトルとして設定し、method
属性をpost
に設定して<form>
タグを使用して、フォームがPOSTリクエストを送信することを示します。
名前がfirstname
とlastname
の2つのテキストフィールドがあります。後でビュー関数でユーザーが送信したフォームデータにアクセスするために、これらの名前を使用します。
名前がemail
の電子メールフィールド、学生の年齢のための数字フィールド、および学生のバイオのためのテキストエリアがあります。
最後に、フォームの末尾に提出ボタンがあります。
開発サーバーが実行されている状態で、ブラウザを使用して/create
ルートに移動します。
http://127.0.0.1:5000/create
次のようなWebフォームと提出ボタンがある新しい学生を追加ページが表示されます:
フォームに入力して送信すると、サーバーにPOSTリクエストを送信しますが、/create
ルートでPOSTリクエストを処理していないため、何も起こりません。
app.py
を開いて、ユーザーが送信したPOSTリクエストを処理します。
/create
ルートを以下のように編集します:
ファイルを保存して閉じます。
if request.method == 'POST'
条件の内側でPOSTリクエストを処理します。ユーザーがrequest.form
オブジェクトから提出したファーストネーム、ラストネーム、メール、年齢、およびバイオを抽出します。int()
Python関数を使用して文字列として渡された年齢を整数に変換します。Student
モデルを使用してstudent
オブジェクトを構築します。データベースセッションに学生オブジェクトを追加し、トランザクションをコミットします。
最後に、新しく追加された学生を既存の学生の下に表示できるインデックスページにユーザーをリダイレクトします。
開発サーバーを実行した状態で、ブラウザを使用して/create
ルートに移動します:
http://127.0.0.1:5000/create
フォームにデータを入力して送信します。
新しく追加された学生が表示されるインデックスページにリダイレクトされます。
新しい学生を追加する機能があるので、ナビゲーションバーに作成ページへのリンクを追加する必要があります。 base.html
を開きます:
<body>
タグを編集して、作成
リンクのhref
属性の値を変更します:
ファイルを保存して閉じます。
インデックスページをリフレッシュすると、ナビゲーションバーの作成リンクが機能することに気付くでしょう。
今、新しい学生を追加するためのWebフォームがあるページがあります。Webフォームの詳細については、FlaskアプリケーションでWebフォームを使用する方法を参照してください。より高度で安全なWebフォームの管理方法については、Flask-WTFを使用したWebフォームの使用と検証方法を参照してください。次に、既存の学生データを編集するためのページを追加します。
ステップ6 — レコードの編集
このステップでは、既存の学生データを編集するための新しいページをアプリケーションに追加します。学生のデータをIDに基づいて編集するための新しい/ID/edit/
ルートを追加します。
app.py
を開いてください:
ファイルの末尾に次のルートを追加します。これにより、IDを使用して編集したい学生エントリを取得します。後で作成するWebフォームを介して送信された新しい学生データを抽出します。その後、学生データを編集して、ユーザーをインデックスページにリダイレクトします:
ファイルを保存して閉じてください。/<int:student_id>/edit/
というルートがあります。これは、student_id
をURL変数として受け取り、そのIDをedit()
ビュー関数に渡します。
get_or_404()
クエリメソッドをStudent
モデルで使用して、指定された学生IDに関連付けられた学生を取得します。データベースに指定されたIDの学生が存在しない場合、404 Not Found
エラーが返されます。
指定されたIDに関連付けられた学生がある場合、コードの実行はif request.method == 'POST'
条件に進みます。リクエストがフォームを送信しなかったGETリクエストの場合、この条件はfalseとなり、その内部のコードはスキップされ、return render_template('edit.html', student=student)
の行まで進みます。これにより、edit.html
テンプレートがレンダリングされ、データベースから取得した学生オブジェクトが渡され、現在の学生データで学生ウェブフォームを入力できます。このedit.html
テンプレートを後で作成します。
ユーザーが学生データを編集してフォームを送信すると、if request.method == 'POST'
内のコードが実行されます。送信された学生データをrequest.form
オブジェクトから対応する変数に抽出します。student
オブジェクトの各属性を新しく送信されたデータに設定して、Step 2で行ったように列の値を変更します。ウェブフォームのフィールドに変更が行われなかった場合、その列の値はデータベースで変わりません。
学生データを新しく送信されたデータに設定した後、学生オブジェクトをデータベースセッションに追加し、変更をコミットします。最後に、ユーザーをインデックスページにリダイレクトします。
次に、ユーザーが編集を行うページを作成する必要があります。新しいedit.html
テンプレートを開きます。
新しいファイルには、create.html
ファイルにあるものと類似したウェブフォームがあり、現在の学生データがフィールドのデフォルト値として設定されています。以下のコードを追加してください:
ファイルを保存して閉じます。
タイトルには学生の名前と姓が含まれています。各入力フィールドの value
属性とバイオテキストエリアの値は、edit()
ビュー関数から edit.html
テンプレートに渡された student
オブジェクト内の対応する値に設定されます。
次に、次のURLに移動して最初の学生の詳細を編集します:
http://127.0.0.1:5000/1/edit
次のようなページが表示されます:
学生データを編集してフォームを送信します。インデックスページにリダイレクトされ、学生の情報が更新されます。
次に、インデックスページの各学生の下に 編集 ボタンを追加して、その編集ページにリンクします。 index.html
テンプレートファイルを開きます:
この index.html
ファイル内の for
ループを以下のように正確に編集します:
ファイルを保存して閉じます。
ここでは、<a>
タグを追加して、student.id
値を 編集 リンクとして各学生の編集ページにリンクさせます。
これで、既存の学生を編集するためのページができました。次に、データベースから学生を削除する 削除 ボタンを追加します。
ステップ7 — レコードの削除
このステップでは、既存の学生を削除するための新しいルートと削除ボタンを追加します。
まず、POSTリクエストを受け入れる新しい/id/delete
ルートを追加します。新しいdelete()
ビュー関数は、削除したい学生のIDを受け取り、存在する場合はStudent
モデルのget_or_404()
クエリメソッドにIDを渡し、指定されたIDの学生がデータベースに見つからなかった場合は404 Not Found
ページで応答します。
app.py
を編集します:
次のルートをファイルの末尾に追加します:
ファイルを保存して閉じます。
ここでは、通常のapp.route
デコレーターの代わりに、app.post
デコレーターを使用します。これはFlaskバージョン2.0.0で導入され、一般的なHTTPメソッドのショートカットが追加されました。たとえば、@app.post("/login")
は@app.route("/login", methods=["POST"])
のショートカットです。これにより、このビュー関数はPOSTリクエストのみを受け付けることになり、ブラウザで/ID/delete
ルートに移動すると405 Method Not Allowed
エラーが返されます。なぜなら、ウェブブラウザはデフォルトでGETリクエストを行うからです。学生を削除するには、ユーザーがボタンをクリックしてこのルートにPOSTリクエストを送信します。
このdelete()
ビュー関数は、student_id
URL変数を介して削除する学生のIDを受け取ります。学生を取得し、student
変数に保存するためにget_or_404()
メソッドを使用し、学生が存在しない場合は404 Not Found
で応答します。行db.session.delete(student)
でデータベースセッションのdelete()
メソッドを使用し、学生オブジェクトを渡します。これにより、トランザクションがコミットされるときに学生が削除されるようにセッションが設定されます。他に変更を加える必要がないため、db.session.commit()
を使用してトランザクションを直接コミットします。最後に、ユーザーをインデックスページにリダイレクトします。
次に、index.html
テンプレートを編集して学生を削除ボタンを追加します。
for
ループを編集して、Editリンクの直下に新しい<form>
タグを追加してください。
ファイルを保存して閉じます。
ここでは、delete()
ビュー関数にPOSTリクエストを送信するWebフォームがあります。student_id
パラメーターにstudent.id
を引数として渡して、削除する学生エントリを指定します。confirm()
メソッド関数はWebブラウザで利用可能で、リクエストを送信する前に確認メッセージを表示します。
今、インデックスページを更新してください。
各学生エントリの下にDelete Studentボタンが表示されます。それをクリックして、削除を確認してください。インデックスページにリダイレクトされ、その学生がもう表示されなくなります。
これで、学生管理アプリケーションでデータベースから学生を削除する方法ができました。
結論
FlaskとFlask-SQLAlchemyを使用してSQLiteデータベースを使った小さなFlask Webアプリケーションを構築しました。データベースに接続する方法、テーブルを表すデータベースモデルを設定する方法、データベースにアイテムを追加する方法、テーブルをクエリする方法、データベースデータを変更する方法を学びました。
アプリケーションでSQLAlchemyを使用すると、Pythonのクラスとオブジェクトを使用してSQLデータベースを管理できます。SQLiteの代わりに、他のデータベースエンジンを使用することができ、接続に責任を持つSQLALCHEMY_DATABASE_URI
設定以外に、コアアプリケーションコードを変更する必要はありません。これにより、最小限のコード変更で、1つのSQLデータベースエンジンから別のエンジンに移行できます。詳細については、Flask-SQLAlchemyドキュメントを参照してください。
Flaskについてもっと読みたい場合は、FlaskでWebアプリケーションを構築する方法シリーズの他のチュートリアルをチェックしてください。