序章

Webアプリケーションでは、通常、データの整理されたコレクションであるデータベースが必要です。 データベースを使用して、効率的に取得および操作できる永続データを保存および維持します。 たとえば、ソーシャルメディアアプリケーションでは、ユーザーデータ(個人情報、投稿、コメント、フォロワー)が効率的に操作できる方法で保存されているデータベースがあります。 さまざまな要件や条件に応じて、データベースにデータを追加、取得、変更、または削除できます。 Webアプリケーションでは、これらの要件は、ユーザーが新しい投稿を追加したり、投稿を削除したり、アカウントを削除したりする場合があります。これにより、投稿が削除される場合と削除されない場合があります。 データを操作するために実行するアクションは、アプリケーションの特定の機能によって異なります。 たとえば、タイトルのない投稿をユーザーに追加させたくない場合があります。

Flask は、Python言語でWebアプリケーションを作成するための便利なツールと機能を提供する軽量のPythonWebフレームワークです。 SQLite は、シンプルで高速なオープンソースの SQLエンジンであり、Pythonで使用してアプリケーションデータを保存および操作できます。 SQLiteはPythonでうまく機能します。これは、Python標準ライブラリが sqlite3モジュールを提供し、何もインストールせずにSQLiteデータベースと対話するために使用できるためです。 PythonでSQLiteを使用すると、他のデータベースエンジンと比較して最小限のセットアップも必要になります。

このチュートリアルでは、FlaskでSQLiteを使用して、CRUD(作成、読み取り、更新、削除)をカバーする基本的なデータ操作を実行する方法を示す小さなWebアプリケーションを構築します。 Webアプリケーションは、インデックスページに投稿を表示する基本的なブログになります。 ユーザーは、個々の投稿を作成、編集、および削除できます。

前提条件

ステップ1—データベースのセットアップ

このステップでは、データ(アプリケーションのブログ投稿)を保存するために使用するSQLiteデータベースを設定します。 次に、データベースにいくつかのエントリ例を入力します。

sqlite3 モジュールを使用して、データベースと対話します。データベースは、標準のPythonライブラリですぐに利用できます。

SQLiteのデータはテーブルと列に保存されるため、最初に次のテーブルを作成する必要があります。 posts 必要な列で。 作成します .sql を作成するためのSQLコマンドを含むファイル posts いくつかの列を持つテーブル。 次に、このスキーマファイルを使用してデータベースを作成します。

と呼ばれるデータベーススキーマファイルを開きます schema.sql あなたの中に flask_app ディレクトリ:

  1. nano schema.sql

このファイル内に次のSQLコマンドを入力します。

フラスコ_app/schema.sql
DROP TABLE IF EXISTS posts;

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

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

このスキーマファイルでは、最初に posts すでに存在する場合はテーブル。 これにより、という名前の別のテーブルの可能性が回避されます posts 既存の場合、混乱する動作が発生する可能性があります(たとえば、列が異なる場合)。 テーブルをまだ作成していないため、SQLコマンドは実行されないため、ここでは当てはまりません。 これにより、このスキーマファイルを実行するたびに既存のデータがすべて削除されることに注意してください。 この目的のために、このスキーマは1回だけ実行しますが、挿入したデータを削除して空のデータベースから再開するために、もう一度実行することをお勧めします。

次に、 CREATE TABLE posts を作成するには posts 次の列を持つテーブル:

  • id主キーを表す整数。 このキーには、各エントリ(つまり、各ブログ投稿)のデータベースによって一意の値が割り当てられます。 AUTOINCREMENT 投稿IDが自動的にインクリメントされるため、最初の投稿のIDは次のようになります。 1、およびその後に追加された投稿のIDは 2、 等々。 他の投稿が削除された場合でも、各投稿は常に同じIDを持ちます。
  • created:ブログ投稿が作成された時刻。 NOT NULL この列が空であってはならないことを意味し、 DEFAULT 値は CURRENT_TIMESTAMP 値。投稿がデータベースに追加された時刻です。 と同じように id、この列の値は自動的に入力されるため、指定する必要はありません。
  • title:投稿のタイトル。 NOT NULL この列を空にすることはできないことを意味します。
  • content:投稿内容。 NOT NULL この列を空にすることはできないことを意味します。

今、あなたは使用します schema.sql データベースを作成するファイル。 そのためには、SQLiteを生成するPythonファイルを作成します .db これに基づくデータベースファイル schema.sql ファイル。 名前の付いたファイルを開きます init_db.py あなたの中に flask_app ディレクトリ:

  1. nano init_db.py

次のコードを追加します。

フラスコ_app/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 posts (title, content) VALUES (?, ?)",
            ('First Post', 'Content for the first post')
            )

cur.execute("INSERT INTO posts (title, content) VALUES (?, ?)",
            ('Second Post', 'Content for the second post')
            )

connection.commit()
connection.close()

最初にインポートします sqlite3 モジュール。 名前の付いたデータベースファイルへの接続を開きます database.db、Pythonファイルを実行すると作成されます。 次に、 open() 開く機能 schema.sql ファイル。 次に、複数のSQLステートメントを一度に実行する executescript()メソッドを使用してコンテンツを実行します。これにより、 posts テーブル。 データベース内の行を処理できるようにするカーソルオブジェクトを作成します。 この場合、カーソルの execute()メソッドを使用して2つを実行します INSERT 2つのブログ投稿を追加するSQLステートメント posts テーブル。 最後に、変更をコミットして接続を閉じます。

ファイルを保存して閉じてから、を使用してターミナルで実行します。 python 指図:

  1. python init_db.py

ファイルの実行が完了すると、 database.db あなたに表示されます flask_app ディレクトリ。 これは、データベースが正常にセットアップされたことを意味します。

次に、小さなFlaskアプリケーションを作成し、データベースに挿入した2つの投稿を取得して、インデックスページに表示します。

ステップ2—投稿を表示する

このステップでは、データベースにあるブログ投稿が表示されるインデックスページを使用してFlaskアプリケーションを作成します。

プログラミング環境をアクティブにしてFlaskをインストールした状態で、次のファイルを開きます。 app.py あなたの中で編集するため flask_app ディレクトリ:

  1. nano app.py

このファイルはデータベース接続をセットアップし、その接続を使用する単一のFlaskルートを作成します。 次のコードをファイルに追加します。

フラスコ_app/app.py
import sqlite3
from flask import Flask, render_template

app = Flask(__name__)

def get_db_connection():
    conn = sqlite3.connect('database.db')
    conn.row_factory = sqlite3.Row
    return conn


@app.route('/')
def index():
    conn = get_db_connection()
    posts = conn.execute('SELECT * FROM posts').fetchall()
    conn.close()
    return render_template('index.html', posts=posts)

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

上記のコードでは、最初に sqlite3 データベースに接続するために使用するモジュール。 次に、インポートします Flask クラスと render_template() からの機能 flask パッケージ。 と呼ばれるFlaskアプリケーションインスタンスを作成します app. と呼ばれる関数を定義します get_db_connection()、への接続を開きます database.db 以前に作成したデータベースファイルで、row_factory属性をに設定します sqlite3.Row そのため、名前に基づいて列にアクセスできます。 これは、データベース接続が通常のPythonディクショナリのように動作する行を返すことを意味します。 最後に、関数は conn データベースへのアクセスに使用する接続オブジェクト。

次に、 app.route() Flaskビュー関数を作成するためのデコレータ index(). あなたは get_db_connection() データベース接続を開く関数。 次に、SQLクエリを実行して、postsテーブルからすべてのエントリを選択します。 fetchall()メソッドを使用して、クエリ結果のすべての行をフェッチします。これにより、前の手順でデータベースに挿入した投稿のリストが返されます。

を使用してデータベース接続を閉じます close() メソッドとレンダリングの結果を返します index.html テンプレート。 あなたも合格します posts データベースから取得した結果を含む引数としてのオブジェクト。 これにより、次のブログ投稿にアクセスできるようになります。 index.html テンプレート。

データベースにある投稿をインデックスページに表示するには、最初にベーステンプレートを作成します。このテンプレートには、コードの繰り返しを避けるために他のテンプレートでも使用されるすべての基本的なHTMLコードが含まれます。 次に、を作成します index.html レンダリングしたテンプレートファイル index() 関数。 テンプレートの詳細については、Flaskアプリケーションでテンプレートを使用する方法を参照してください。

テンプレートディレクトリを作成し、という名前の新しいテンプレートを開きます base.html:

  1. mkdir templates
  2. nano templates/base.html

内に次のコードを追加します base.html ファイル:

フラスコ_app/templates / base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %}- FlaskApp</title>
    <style>
        .post {
            padding: 10px;
            margin: 5px;
            background-color: #f3f3f3
        }

        nav a {
            color: #d64161;
            font-size: 3em;
            margin-left: 50px;
            text-decoration: none;
        }
    </style>
</head>
<body>
    <nav>
        <a href="{{ url_for('index') }}">FlaskApp</a>
        <a href="#">About</a>
    </nav>
    <hr>
    <div class="content">
        {% block content %} {% endblock %}
    </div>
</body>
</html>

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

この基本テンプレートには、他のテンプレートで再利用する必要があるすべてのHTMLボイラープレートが含まれています。 The title 各ページのタイトルを設定するためにブロックが置き換えられ、 content ブロックは各ページのコンテンツに置き換えられます。 ナビゲーションバーには2つのリンクがあります。1つは、を使用するインデックスページ用です。 url_for() リンクするヘルパー関数 index() 表示機能、およびアプリケーションに1つを含めることを選択した場合は、[バージョン情報]ページ用のもう1つ。

次に、というテンプレートを開きます index.html. これは、で参照したテンプレートです。 app.py ファイル:

  1. nano templates/index.html

次のコードを追加します。

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

{% block content %}
    <h1>{% block title %} Posts {% endblock %}</h1>
    {% for post in posts %}
        <div class='post'>
            <p>{{ post['created'] }}</p>
            <h2>{{ post['title'] }}</h2>
            <p>{{ post['content'] }}</p>
        </div>
    {% endfor %}
{% endblock %}

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

上記のコードでは、 base.html テンプレートを作成し、その内容を置き換えます content ブロック。 あなたは <h1> タイトルを兼ねる見出し。

行でJinjaforloopを使用します {% for post in posts %} の各投稿を確認するには posts リスト。 作成日にアクセスするには、 {{ post['created'] }}、タイトル経由 {{ post['title'] }}、および経由での投稿コンテンツ {{ post['content'] }}.

あなたの中に flask_app 仮想環境がアクティブ化されているディレクトリ、アプリケーションについてFlaskに通知します(app.py この場合)を使用して FLASK_APP 環境変数:

  1. export FLASK_APP=app

次に、 FLASK_ENV 環境変数から development アプリケーションを開発モードで実行し、デバッガーにアクセスします。 Flaskデバッガーの詳細については、Flaskアプリケーションでエラーを処理する方法を参照してください。 これを行うには、次のコマンドを使用します(Windowsでは、 set それ以外の export):

  1. export FLASK_ENV=development

次に、アプリケーションを実行します。

  1. flask run

開発サーバーが実行されている状態で、ブラウザーを使用して次のURLにアクセスします。

http://127.0.0.1:5000/

最初の開始時にデータベースに追加した投稿が表示されます。

データベースの投稿をインデックスページに表示しました。 ここで、ユーザーが新しい投稿を追加できるようにする必要があります。 次のステップで、投稿を追加するための新しいルートを追加します。

ステップ3—投稿を作成する

このステップでは、Flaskアプリケーションに新しいルートを追加します。これにより、ユーザーは新しいブログ投稿をデータベースに追加でき、インデックスページに表示されます。

ユーザーが投稿のタイトルと投稿のコンテンツを入力するWebフォームを含むページを追加します。 このフォームは、ユーザーが空のフォームを送信しないように検証されます。 フォームが無効であることをユーザーに通知するには、フラッシュメッセージを使用します。このメッセージは1回だけ表示され、次のリクエストで消えます(たとえば、別のページに移動した場合)。

開発サーバーを実行したままにして、新しいターミナルウィンドウを開きます。

まず、 app.py ファイル:

  1. nano app.py

Webフォームを処理するには、からいくつかのものをインポートする必要があります。 flask パッケージ:

  • 送信されたデータにアクセスするためのグローバルrequestオブジェクト。
  • url_for()関数を使用してURLを生成します。
  • flash()関数は、リクエストが無効な場合にメッセージをフラッシュします。
  • redirect()関数は、データベースに投稿を追加した後、ユーザーをインデックスページにリダイレクトします。

これらのインポートをファイルの最初の行に追加します。

フラスコ_app/app.py
from flask import Flask, render_template, request, url_for, flash, redirect

# ...

The flash() 関数は、フラッシュされたメッセージをクライアントのブラウザセッションに保存します。これには、秘密鍵を設定して、ある要求から別の要求への情報を記憶するセッションを保護する必要があります。 誰にもあなたの秘密鍵へのアクセスを許可してはなりません。 詳細については、セッションのFlaskドキュメントを参照してください。

秘密鍵を追加して設定します SECRET_KEY を介したアプリケーションへの構成 app.config 物体。 の横に追加します app インスタンス定義。

フラスコ_app/app.py

# ...
app = Flask(__name__)
app.config['SECRET_KEY'] = 'your secret key'

秘密鍵は長いランダムな文字列である必要があることに注意してください。 Webフォームと秘密鍵の構成の詳細については、FlaskアプリケーションでWebフォームを使用する方法を参照してください。

次に、最後に次のルートを追加します app.py ファイル:

フラスコ_app/app.py
# ...

@app.route('/create/', methods=('GET', 'POST'))
def create():
    return render_template('create.html')

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

このルートでは、タプルを渡します ('GET', 'POST')methods GET要求とPOST要求の両方を許可するパラメーター。 GETリクエストは、サーバーからデータを取得するために使用されます。 POSTリクエストは、特定のルートにデータを投稿するために使用されます。 デフォルトでは、GETリクエストのみが許可されます。 ユーザーが最初にリクエストしたとき /create GETリクエストを使用してルーティングします。 create.html レンダリングされます。 後でこのルートを編集して、ユーザーが新しい投稿を作成するためのWebフォームに入力して送信するときのPOSTリクエストを処理します。

新しいを開く create.html テンプレート:

  1. nano templates/create.html

次のコードを追加します。

フラスコ_app/templates / create.html
{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Add a New Post {% endblock %}</h1>
    <form method="post">
        <label for="title">Title</label>
        <br>
        <input type="text" name="title"
               placeholder="Post title"
               value="{{ request.form['title'] }}"></input>
        <br>

        <label for="content">Post Content</label>
        <br>
        <textarea name="content"
                  placeholder="Post content"
                  rows="15"
                  cols="60"
                  >{{ request.form['content'] }}</textarea>
        <br>
        <button type="submit">Submit</button>
    </form>
{% endblock %}

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

基本テンプレートを拡張し、見出しをタイトルとして設定し、 <form> 属性を持つタグ method に設定 post フォームがPOSTリクエストを送信することを示します。 名前の付いたテキストフィールドがあります title、のタイトルデータにアクセスするために使用します /create ルート。 テキストフィールドの値を次のように設定します request.form['title'] これは空であるか、フォームが無効な場合はタイトルの保存バージョンであるため、問題が発生したときにタイトルが失われることはありません。

タイトル入力フィールドの後に、という名前のテキスト領域を追加します content 値で {{ request.form['content'] }} フォームが無効な場合に投稿コンテンツを復元します。

最後に、フォームの最後に[送信]ボタンがあります。

これで、開発サーバーが実行されている状態で、ブラウザーを使用してに移動します。 /create ルート:

http://127.0.0.1:5000/create

新しい投稿の追加ページが表示され、投稿タイトルの入力フィールド、投稿のコンテンツのテキスト領域、および送信ボタンが表示されます。

フォームに入力して送信し、サーバーにPOSTリクエストを送信すると、POSTリクエストを処理しなかったため、何も起こりません。 /create ルート。

開ける app.py ユーザーが送信するPOSTリクエストを処理するには:

  1. nano app.py

編集します /create 次のように見えるルート:

フラスコ_app/app.py
# ...

@app.route('/create/', methods=('GET', 'POST'))
def create():
    if request.method == 'POST':
        title = request.form['title']
        content = request.form['content']

        if not title:
            flash('Title is required!')
        elif not content:
            flash('Content is required!')
        else:
            conn = get_db_connection()
            conn.execute('INSERT INTO posts (title, content) VALUES (?, ?)',
                         (title, content))
            conn.commit()
            conn.close()
            return redirect(url_for('index'))

    return render_template('create.html')

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

POSTリクエストは内部で処理します if request.method == 'POST' 調子。 ユーザーが送信したタイトルとコンテンツを request.form 物体。 タイトルが空の場合は、 flash() メッセージをフラッシュする機能 Title is required!. 空のコンテンツの場合も同じようにします。

タイトルとコンテンツの両方が提供されている場合は、を使用してデータベース接続を開きます。 get_db_connection() 関数。 あなたは execute() 実行するメソッド INSERT INTO 新しい投稿をに追加するSQLステートメント posts ユーザーが値として送信するタイトルとコンテンツを含むテーブル。 あなたは ? データをテーブルに安全に挿入するためのプレースホルダー。 トランザクションをコミットして、接続を閉じます。 最後に、ユーザーをインデックスページにリダイレクトします。このページでは、既存の投稿の下に新しい投稿が表示されます。

警告:Python文字列操作を使用してSQLステートメント文字列を動的に作成しないでください。 常に使用してください ? 値を動的に置き換えるためのSQLステートメントのプレースホルダー。 値のタプルを2番目の引数として execute() 値をSQLステートメントにバインドするメソッド。 これにより、SQLインジェクション攻撃が防止されます。

開発サーバーが実行されている状態で、ブラウザを使用してに移動します /create ルート:

http://127.0.0.1:5000/create

フォームに記入して送信します。

新しい投稿が表示されるインデックスページにリダイレクトされます。

タイトルのないフォームまたはコンテンツのないフォームを送信すると、投稿はデータベースに追加されず、インデックスページにリダイレクトされず、その理由に関するフィードバックを受け取ることもありません。 これは、フラッシュされたメッセージがまだどこにも表示されないように設定していないためです。

開ける base.html ナビゲーションバーの[作成]ページへのリンクを追加し、その下に点滅するメッセージを表示します。

  1. nano templates/base.html

次のようにファイルを編集します。

フラスコ_app/templates / base.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %} - FlaskApp</title>
    <style>
        .post {
            padding: 10px;
            margin: 5px;
            background-color: #f3f3f3
        }

        nav a {
            color: #d64161;
            font-size: 3em;
            margin-left: 50px;
            text-decoration: none;
        }

        .alert {
            padding: 20px;
            margin: 5px;
            color: #970020;
            background-color: #ffd5de;
        }
    </style>
</head>
<body>
    <nav>
        <a href="{{ url_for('index') }}">FlaskApp</a>
        <a href="{{ url_for('create') }}">Create</a>
        <a href="#">About</a>
    </nav>
    <hr>
    <div class="content">
        {% for message in get_flashed_messages() %}
            <div class="alert">{{ message }}</div>
        {% endfor %}

        {% block content %} {% endblock %}
    </div>
</body>
</html>

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

ここで、新しいを追加します <a> [作成]ページを指すナビゲーションバーへのリンク。

ジンジャを使う for フラッシュされたメッセージを通過するためにループします。 これらはで利用可能です get_flashed_messages() 特殊機能。 各メッセージはに表示されます <div> と呼ばれるCSSクラスのタグ alert. あなたはこれをスタイリングします <div> 内のタグ <style> のタグ <head> セクション。

インデックスページを更新すると、ナビゲーションバーに新しいリンクが表示されます。

作成リンクをクリックして、空のフォームを送信します。 「タイトルが必要です!」というメッセージが点滅します。

タイトルフィールドに入力し、コンテンツテキスト領域を空のままにします。 もう一度フォームを送信すると、「コンテンツが必要です!」というメッセージが表示されます。 メッセージ。 「タイトルが必要です!」に注目してください。 メッセージが消えました。 これは、フラッシュメッセージであり、永続的なメッセージではないためです。

これで、新しい投稿を追加する方法があります。 次に、ユーザーが既存の投稿を編集できるようにするための新しいルートを追加します。

ステップ4—投稿を編集する

このステップでは、ユーザーが既存の投稿を編集できるように、アプリケーションに新しいルートを追加します。

まず、コードの繰り返しを回避し、コードを分離して保守を容易にするために、IDを取得し、それに関連付けられた投稿をデータベースから取得する新しい関数を追加します。 この関数を使用して、編集する投稿データを取得し、次のステップで削除する場合の投稿を取得します。

開ける app.py:

  1. nano app.py

投稿を取得するために使用する関数は、 404 Not Found リクエストされた投稿のIDが既存の投稿のいずれとも一致しない場合はエラーになります。 これを行うには、 abort()関数を使用します。この関数は、要求を中止し、エラーメッセージで応答します。 詳細については、Flaskアプリケーションでエラーを処理する方法を参照してください。

追加します abort() インポートへの機能:

フラスコ_app/app.py
from flask import Flask, render_template, request, url_for, flash, redirect, abort

と呼ばれる新しい関数を追加します get_post() あなたの下 get_db_connection() 関数:

フラスコ_app/app.py

# ...

def get_db_connection():
    conn = sqlite3.connect('database.db')
    conn.row_factory = sqlite3.Row
    return conn

def get_post(post_id):
    conn = get_db_connection()
    post = conn.execute('SELECT * FROM posts WHERE id = ?',
                        (post_id,)).fetchone()
    conn.close()
    if post is None:
        abort(404)
    return post

# ...

この新しい関数には post_id 取得して返す投稿を決定する引数。 とデータベース接続を開きます get_db_connection() SQLクエリを実行して、指定された投稿に関連付けられた投稿を取得します post_id 価値。 あなたはで投稿を取得します fetchone() メソッド、それをに保存します post 変数を入力し、接続を閉じます。

の場合 post 変数の値は None、データベースに結果が見つからなかったことを意味します。 abort() 以前にインポートした関数で応答します 404 エラーコードと関数は実行を終了します。 ただし、投稿が見つかった場合は、の値を返します post 変数。

次に、ファイルの最後に投稿を編集するための新しいルートを追加します。

フラスコ_app/app.py
# ...

@app.route('/<int:id>/edit/', methods=('GET', 'POST'))
def edit(id):
    post = get_post(id)

    if request.method == 'POST':
        title = request.form['title']
        content = request.form['content']

        if not title:
            flash('Title is required!')

        elif not content:
            flash('Content is required!')

        else:
            conn = get_db_connection()
            conn.execute('UPDATE posts SET title = ?, content = ?'
                         ' WHERE id = ?',
                         (title, content, id))
            conn.commit()
            conn.close()
            return redirect(url_for('index'))

    return render_template('edit.html', post=post)

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

ルートを使用します /<int:id>/edit/、 と int: 正の整数を受け入れるコンバーターであること。 と id 編集する投稿を決定するURL変数です。 例えば、 /2/edit/ 次のIDで投稿を編集できます 2. IDはURLからに渡されます edit() ビュー機能。 の値を渡します id への議論 get_post() 指定されたIDに関連付けられた投稿をデータベースからフェッチする関数。 これは次のように応答することを忘れないでください 404 Not Found 指定されたIDの投稿が存在しない場合はエラーになります。

最後の行は、というテンプレートファイルをレンダリングします edit.html、およびパス post 投稿データを持つ変数。 これを使用して、編集ページに既存のタイトルとコンテンツを表示します。

The if request.method == 'POST' ブロックは、ユーザーが送信する新しいデータを処理します。 新しい投稿を追加するのと同様に、タイトルとコンテンツを抽出します。 タイトルまたはコンテンツが提供されていない場合は、メッセージをフラッシュします。

フォームが有効な場合は、データベース接続を開き、 UPDATE を更新するSQLステートメント posts 新しいタイトルと新しいコンテンツを設定してテーブルを作成します。データベース内の投稿のIDは、URLに含まれていたIDと同じです。 トランザクションをコミットし、接続を閉じて、インデックスページにリダイレクトします。

次に、ユーザーが編集できるページを作成する必要があります。 新しいを開く edit.html テンプレート:

  1. nano templates/edit.html

次のコードを追加します。

フラスコ_app/templates / edit.html
{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Edit "{{ post['title'] }}" {% endblock %}</h1>
    <form method="post">
        <label for="title">Title</label>
        <br>
        <input type="text" name="title"
               placeholder="Post title"
               value="{{ request.form['title'] or post['title'] }}"></input>
        <br>

        <label for="content">Post Content</label>
        <br>
        <textarea name="content"
                  placeholder="Post content"
                  rows="15"
                  cols="60"
                  >{{ request.form['content'] or post['content'] }}</textarea>
        <br>
        <button type="submit">Submit</button>
    </form>
{% endblock %}

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

これは、のコードに似ています create.html テンプレート。ただし、行のページのタイトル内に投稿のタイトルを表示する場合を除きます。 {% block title %} Edit "{{ post['title'] }}" {% endblock %}、入力の値 {{ request.form['title'] or post['title'] }}、およびのテキスト領域の値 {{ request.form['content'] or post['content'] }}. これにより、リクエストに保存されているデータが存在する場合はそれが表示されます。 それ以外の場合は、 post 現在のデータベースデータを含むテンプレートに渡された変数。

開発サーバーが実行されている状態で、ブラウザーを使用して次のURLに移動し、最初の投稿を編集します。

http://127.0.0.1:5000/1/edit

次のようなページが表示されます。

投稿を編集してフォームを送信します。 インデックスページに適用された変更が表示されます。 タイトルなしまたはコンテンツなしでフォームを送信すると、フラッシュメッセージが表示されます。

次に、インデックスページの各投稿の編集ページを指すリンクを追加する必要があります。 を開きます index.html テンプレートファイル:

  1. nano templates/index.html

次のようにファイルを編集します。

フラスコ_app/templates / index.html

{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Posts {% endblock %}</h1>
    {% for post in posts %}
        <div class='post'>
            <p>{{ post['created'] }}</p>
            <h2>{{ post['title'] }}</h2>
            <p>{{ post['content'] }}</p>
            <a href="{{ url_for('edit', id=post['id']) }}">Edit</a>
        </div>
    {% endfor %}
{% endblock %}

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

追加しました <a> にリンクするタグ edit() ビュー機能。 あなたはあなたが持っている投稿IDを渡します post['id'])url_for() 投稿の編集リンクを生成する関数。 これにより、その下にある各投稿の編集ページへのリンクが追加されます。

インデックスページを更新し、編集リンクをクリックして投稿を編集します。

これで、新しい投稿を追加したり、既存の投稿を編集したりできます。 次に、ユーザーが既存の投稿を削除できるようにするボタンを追加します。

ステップ5—投稿を削除する

このステップでは、ユーザーが投稿を削除できるように、[編集]ページに[削除]ボタンを追加します。

まず、新しいものを追加します /id/delete POSTリクエストを受け入れるルート。 edit() ビュー機能。 あなたの新しい delete() ビュー機能は、URLから削除される投稿のIDを受け取り、を使用してそれを取得します get_post() 関数を作成し、存在する場合はデータベースから削除します。

を開きます app.py ファイル:

  1. nano app.py

最後に次のルートを追加します。

フラスコ_app/app.py
# ...

@app.route('/<int:id>/delete/', methods=('POST',))
def delete(id):
    post = get_post(id)
    conn = get_db_connection()
    conn.execute('DELETE FROM posts WHERE id = ?', (id,))
    conn.commit()
    conn.close()
    flash('"{}" was successfully deleted!'.format(post['title']))
    return redirect(url_for('index'))

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

このビュー関数は、POSTリクエストのみを受け入れます。 methods パラメータ。 これは、 /ID/delete ブラウザのルートは 405 Method Not Allowed エラー。WebブラウザはデフォルトでGETリクエストを使用しているためです。 投稿を削除するには、ユーザーはこのルートにPOSTリクエストを送信するボタンをクリックします。

この関数は、削除する投稿のIDを受け取ります。 このIDを使用して、 get_post() 関数。 これは、 404 Not Found 指定されたIDの投稿が存在しない場合はエラーになります。 データベース接続を開き、 DELETE FROM 投稿を削除するSQLコマンド。 あなたが使う WHERE id = ? 削除する投稿を指定します。

データベースへの変更をコミットし、接続を閉じます。 メッセージをフラッシュして、投稿が正常に削除されたことをユーザーに通知し、インデックスページにリダイレクトします。

テンプレートファイルはレンダリングしないことに注意してください。 これは、[編集]ページに[削除]ボタンを追加するだけだからです。

を開きます edit.html テンプレートファイル:

  1. nano templates/edit.html

次に、以下を追加します <hr><form> 直前のタグ {% endblock %} ライン:

フラスコ_app/templates / edit.html
        <button type="submit">Submit</button>
    </form>


    <hr>
    <form action="{{ url_for('delete', id=post['id']) }}" method="POST">
        <input type="submit" value="Delete Post"
                onclick="return confirm('Are you sure you want to delete this post?')">
    </form>
{% endblock %}

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

ここに、POSTリクエストを送信するWebフォームがあります。 delete() ビュー機能。 あなたは合格します post['id'] 削除する投稿を指定します。 Webブラウザーで使用可能なconfirm()メソッドを使用して、要求を送信する前に確認メッセージを表示します。

次に、投稿の[編集]ページに再度移動して、削除してみます。

http://127.0.0.1:5000/1/edit

削除を確認すると、インデックスページにリダイレクトされ、投稿は表示されなくなります。 ナビゲーションバーの下に、投稿が正常に削除されたことを通知するフラッシュメッセージが表示されます。

これで、Flaskアプリケーションのデータベースから不要な投稿を削除する方法があります。

結論

SQLiteデータベースと通信する小さなWebブログを作成しました。 Flaskアプリケーションには、データベースへの新しいデータの追加、データの取得とページへの表示、既存のデータの編集と削除などの基本的な機能があります。

PythonとFlaskでSQLiteを使用する方法の詳細については、次のチュートリアルを参照してください。

Flaskの詳細については、Flaskシリーズの他のチュートリアルをご覧ください。