序章

Flask は、Python言語を使用してWebアプリケーションを構築するためのフレームワークです。 Flaskを使用すると、SQLiteをデータベースエンジンとして使用してアプリケーションデータを保存できます。

Markdown は、読みやすいテキスト形式でコンテンツを書き込むプロセスで一般的に使用されるマークアップ言語です。 Markdownを使用すると、見出し、リンク、画像などの機能を使用してプレーンテキストをフォーマットし、テキストをHTMLに変換できます。これには、これらのフォーマット機能が含まれます。 Markdownの使用方法については、Markdown構文標準を確認してください。

Python-Markdown は、MarkdownテキストをHTMLに変換できるPythonライブラリです。 これは主にMarkdown標準に準拠していますが、標準のMarkdown構文とはわずかな違いがあります。

このチュートリアルでは、Flask、SQLite、およびPython-Markdownを使用して、Markdownを使用したテキストのフォーマットをサポートする小さなメモを取るWebアプリケーションを構築します。 このアプリを使用すると、ユーザーは、見出し、リンク、リスト、画像、その他の機能を備えたメモを表示、作成、フォーマットできます。 Bootstrapツールキットを使用してアプリケーションのスタイルを設定します。

前提条件

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

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

ステップ1—依存関係を設定する

このステップでは、Python環境をアクティブ化し、pipパッケージインストーラーを使用してFlaskとPython-Markdownをインストールします。 次に、メモを保存するために使用するデータベースを作成し、それにサンプルデータを追加します。

まず、プログラミング環境をまだアクティブにしていない場合はアクティブにします。

  1. source env/bin/activate

プログラミング環境をアクティブにしたら、次のコマンドを使用してFlaskとPython-Markdownライブラリをインストールします。

  1. pip install flask markdown

次に、というデータベーススキーマファイルを作成します schema.sql、を作成するためのSQLコマンドが含まれます notes テーブル。 内のファイルを開きます flask_notes ディレクトリ:

  1. nano schema.sql

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

フラスコノート/スキーマ.sql
DROP TABLE IF EXISTS notes;

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

このSQLファイルでは、最初に、という名前の既存のテーブルを削除します。 notes、問題を引き起こす可能性があります。 これにより、 notes 表は、このSQLで説明されているとおりです。 これにより、これらのSQLコマンドを使用するたびにデータベースにあるすべてのコンテンツが削除されるため、このチュートリアルを終了して最終結果を試すまで、Webアプリケーションに重要なコンテンツを書き込まないようにしてください。

あなたは CREATE TABLE notes 作成するステートメント notes 次の列を持つテーブル:

  • id主キーを表す整数。 データベースは、これに各エントリに一意の値を割り当てます(メモ)。
  • created:ノートの作成日。 メモがデータベースに追加された時刻が自動的に入力されます。
  • content:メモの内容。

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

を使用してデータベースを作成するには schema.sql ファイル、という名前のファイルを開きます init_db.pyflask_notes ディレクトリ:

  1. nano init_db.py

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

フラスコ_notes/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 notes (content) VALUES (?)", ('# The First Note',))
cur.execute("INSERT INTO notes (content) VALUES (?)", ('_Another note_',))
cur.execute("INSERT INTO notes (content) VALUES (?)", ('Visit [this page](https://www.digitalocean.com/community/tutorials) for more tutorials.',))

connection.commit()
connection.close()

ここでは、最初にインポートします sqlite3 モジュール。 次に、というファイルに接続します database.db このプログラムを実行すると作成されます。 database.db アプリケーションのすべてのデータを保持するデータベースです。 次に、 schema.sql ファイルを作成し、複数のSQLステートメントを一度に実行する executescript()メソッドを使用して実行します。 これにより、 notes テーブル。

カーソルオブジェクトを使用して、いくつかを実行します INSERT 3つのメモを作成するSQLステートメント。 ここではMarkdown構文を使用しています:最初のメモは <h1> 見出しでは、2番目のメモは斜体で、3番目のメモにはリンクが含まれています。 あなたは ? execute()メソッドのプレースホルダーであり、メモの内容を含むタプルを渡して、データベースにデータを安全に挿入します。

最後に、変更をコミットして接続を閉じます。

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

プログラムを実行します。

  1. python init_db.py

実行後、という新しいファイル database.db あなたに表示されます flask_notes ディレクトリ。

環境をアクティブ化し、FlaskとPython-Markdownをインストールし、SQLiteデータベースを作成しました。 次に、データベースからMarkdownノートを取得し、HTMLに変換して、アプリケーションのホームページに表示します。

ステップ2—インデックスページにメモを表示する

このステップでは、データベースに接続し、データベースにあるサンプルデータを表示するFlaskアプリケーションを作成します。 データベース内のマークダウンテキストをHTMLに変換してから、インデックスページにレンダリングします。

まず、を作成します app.py あなたの中のアプリケーションファイル flask_notes ディレクトリ:

  1. nano app.py

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

フラスコノート/app.py
import sqlite3
import markdown
from flask import Flask, render_template, request, flash, redirect, url_for

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

最初にインポートします sqlite3 モジュール、 markdown パッケージ、およびFlaskヘルパー。

The get_db_connection() 関数はへの接続を開きます database.db データベースファイルを作成し、row_factory属性を次のように設定します。 sqlite3.Row. これにより、列への名前ベースのアクセスが可能になります。つまり、データベース接続は、通常のPythonディクショナリのように動作する行を返します。 最後に、関数は conn データベースへのアクセスに使用する接続オブジェクト。

その後、次のコードスニペットを追加します。

フラスコノート/app.py
#. . .

app = Flask(__name__)
app.config['SECRET_KEY'] = 'this should be a secret random string'

ここでは、Flaskアプリケーションオブジェクトを作成し、秘密鍵をセキュアセッションに設定します。

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

フラスコノート/app.py
#. . .

@app.route('/')
def index():
    conn = get_db_connection()
    db_notes = conn.execute('SELECT id, created, content FROM notes;').fetchall()
    conn.close()

    notes = []
    for note in db_notes:
       note = dict(note)
       note['content'] = markdown.markdown(note['content'])
       notes.append(note)

    return render_template('index.html', notes=notes)

The index() 関数はFlaskビュー関数で、特殊な機能を使用して装飾された関数です。 @app.route デコレータ。 Flaskは、この関数の戻り値を、WebブラウザーなどのHTTPクライアントが表示するHTTP応答に変換します。

の中に index() ビュー機能、データベース接続を開き、実行します SELECT ID、作成日、およびのすべての行のコンテンツをフェッチするSQLステートメント notes テーブル。 あなたは fetchall() すべての行のリストを取得し、このデータをに保存するメソッド db_notes 変数。 次に、接続を閉じます。

メモの内容をMarkdownからHTMLに変換するには、という新しい空のリストを作成します。 notes. あなたはループします db_notes 各ノートをリストして変換します sqlite3.Row を使用して通常のPython辞書に dict() 割り当てを可能にするPython関数。 次に、 markdown.markdown() の値を変換する関数 note['content'] HTMLに。 たとえば、 markdown.markdown('#Hi') 文字列を返します '<h1>Hi</h1>' マークダウンで # を表します <h1> 見出し。 変更後 note['content']、メモをに追加します notes リスト。

最後に、というテンプレートファイルをレンダリングします index.html、それを渡す notes リスト。

すべての追加後、ファイルは次のようになります。

フラスコノート/app.py
import sqlite3
import markdown
from flask import Flask, render_template, request, flash, redirect, url_for

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


app = Flask(__name__)
app.config['SECRET_KEY'] = 'this should be a secret random string'


@app.route('/')
def index():
    conn = get_db_connection()
    db_notes = conn.execute('SELECT id, created, content FROM notes;').fetchall()
    conn.close()

    notes = []
    for note in db_notes:
       note = dict(note)
       note['content'] = markdown.markdown(note['content'])
       notes.append(note)

    return render_template('index.html', notes=notes)

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

次に、ベーステンプレートと index.html テンプレートファイル。

あなたの中で flask_notes ディレクトリ、作成 templates ディレクトリを開き、というファイルを開きます base.html その中:

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

中に次のコードを追加します base.html; ここではBootstrapを使用していることに注意してください。 FlaskのHTMLテンプレートに慣れていない場合は、 Python3でFlaskを使用してWebアプリケーションを作成する方法のステップ3をお読みください。

フラスコノート/テンプレート/base.html
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <title>{% block title %} {% endblock %}</title>
  </head>
  <body>
    <nav class="navbar navbar-expand-md navbar-light bg-light">
        <a class="navbar-brand" href="{{ url_for('index')}}">FlaskNotes</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav">
            <li class="nav-item active">
                <a class="nav-link" href="#">About</a>
            </li>
            </ul>
        </div>
    </nav>
    <div class="container">
        {% for message in get_flashed_messages() %}
            <div class="alert alert-danger">{{ message }}</div>
        {% endfor %}
        {% block content %} {% endblock %}
    </div>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  </body>
</html>

前のブロックのコードのほとんどは、標準のHTMLであり、Bootstrapに必要なコードです。 The <meta> タグは、Webブラウザの情報を提供します。 <link> タグはブートストラップCSSファイルとリンクします <script> タグは、いくつかの追加のブートストラップ機能を可能にするJavaScriptコードへのリンクです。

The <title>{% block title %} {% endblock %}</title> タグを使用すると、継承するテンプレートでカスタムタイトルを定義できます。 あなたは for message in get_flashed_messages() 警告やアラートなどのフラッシュされたメッセージを表示するためにループします。 The {% block content %} {% endblock %} プレースホルダーは、継承するテンプレートがコンテンツを配置する場所であり、すべてのテンプレートに、このベーステンプレートが繰り返しを回避するために提供する追加のコードが含まれるようにします。

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

次に、を作成します index.html これを拡張するファイル base.html ファイル:

  1. nano templates/index.html

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

フラスコノート/テンプレート/インデックス.html

{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Welcome to FlaskNotes {% endblock %}</h1>
    {% for note in notes %}
    <div class="card">
        <div class="card-body">
            <span class="badge badge-primary">#{{ note['id'] }}</span>
            <span class="badge badge-default">{{ note['created'] }}</span>
            <hr>
            <p>{{ note['content'] |safe }}</p>
        </div>
    </div>
    <hr>
    {% endfor %}
{% endblock %}

ここで拡張します base.html、タイトルを定義し、 for ブートストラップカードの各ノートを表示するノートをループします。 ノートのID、ノートの作成日、およびHTMLに変換したノートのコンテンツを表示します。 index() ビュー機能。

あなたは |safe を使用してコンテンツに適用するJinjaフィルター |; これは、Pythonで関数を呼び出すのと似ています( safe(note['content'])). The |safe フィルタを使用すると、ブラウザでHTMLコードをレンダリングできます。適用されていない場合は、HTMLがプレーンテキストとして表示されます。 これは通常、「エスケープHTML」と呼ばれ、悪意のあるHTMLがブラウザで解釈されてクロスサイトスクリプティング(XSS)と呼ばれる危険なセキュリティの脆弱性が発生するのを防ぐセキュリティ機能です。 Python-Markdownライブラリは安全なHTMLを返すため、ブラウザが |safe フィルター。 許可するHTMLコードが安全で信頼できることが確実になるまで、このフィルターを使用しないでください。

詳細については、自動エスケープの制御に関するFlaskのドキュメントを参照してください。

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

Flaskが必要とする環境変数を設定し、次のコマンドを使用してアプリケーションを実行します。

  1. export FLASK_APP=app
  2. export FLASK_ENV=development
  3. flask run

The FLASK_APP 環境変数は、実行するアプリケーションを指定します( app.py ファイル)。 The FLASK_ENV 環境変数はモードを指定します。 development これは、アプリケーションがデバッガーを実行した状態で開発モードで実行されることを意味します(本番環境でこのモードを使用しないように注意してください)。 を使用してアプリケーションを実行します flask run 指図。

ブラウザを開き、URLを入力します http://127.0.0.1:5000/.

ここでは、各メモがプレーンテキストではなくHTMLとしてフォーマットおよびレンダリングされていることがわかります。

データベースに接続し、メモを取得し、そのコンテンツをMarkdownテキストからHTMLに変換して、インデックスページにレンダリングするFlaskアプリケーションを作成しました。 次に、ユーザーがMarkdown構文を使用して書き込むことができる新しいメモを追加できるようにするルートを追加します。

ステップ3—新しいメモを追加する

このステップでは、ユーザーが新しいメモを取ることができる新しいルートを追加します。 ユーザーはMarkdown構文を使用してメモを書き込むことができます。アプリケーションはメモをデータベースに保存し、適切な形式でインデックスページに表示します。 また、ナビゲーションバーにボタンを追加して、ユーザーをこの新しいページに移動させます。

Webフォームを使用して、ユーザーがFlaskアプリケーションでデータを送信できるようにし、ユーザーが送信したデータをデータベースに保存します。

まず、 app.py 新しいルートを追加するファイル:

  1. nano app.py

次のコードをファイルの最後に追加します。

フラスコノート/app.py
#. . .

@app.route('/create/', methods=('GET', 'POST'))
def create():
    conn = get_db_connection()

    if request.method == 'POST':
        content = request.form['content']
        if not content:
            flash('Content is required!')
            return redirect(url_for('index'))
        conn.execute('INSERT INTO notes (content) VALUES (?)', (content,))
        conn.commit()
        conn.close()
        return redirect(url_for('index'))

    return render_template('create.html')

このルートを使用してWebフォームを介してデータベースに新しいデータを挿入するため、を使用してGETリクエストとPOSTリクエストの両方を許可します。 methods=('GET', 'POST') の中に app.route() デコレータ。 の中に create() ビュー機能では、データベース接続を開きます。

ユーザーが条件を意味するフォームを送信した場合 request.method == 'POST' trueであるため、ユーザーが送信したメモのコンテンツを request.form['content'] それをという変数に保存します content. コンテンツが空の場合は、フラッシュします 'Content is required!' メッセージを送信し、ユーザーをインデックスページにリダイレクトします。 コンテンツが空でない場合は、 INSERT メモの内容をに追加するSQLステートメント notes テーブル。 変更をコミットして接続を閉じてから、ユーザーをインデックスページにリダイレクトします。

リクエストがGETリクエストの場合、つまりユーザーがページにアクセスしたばかりの場合は、次のテンプレートファイルをレンダリングします。 create.html.

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

次に、 create.html テンプレートファイル:

  1. nano templates/create.html

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

フラスコノート/テンプレート/作成.html
{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Add a New Note {% endblock %}</h1>
    <form method="post">
    <div class="form-group">
        <label for="content">Note Content</label>
        <textarea type="text" name="content"
               placeholder="Note content, you can use Markdown syntax" class="form-control"
               value="{{ request.form['content'] }}" autofocus></textarea>
    </div>

    <div class="form-group">
        <button type="submit" class="btn btn-primary">Submit</button>
    </div>
    </form>

{% endblock %}

ここでは、メモの内容にテキスト領域のあるフォームを使用します。 あなたが使う request.form フォームの送信で問題が発生した場合(たとえば、コンテンツが提供されなかった場合)に保存されているフォームデータにアクセスするため。 ユーザーがPOSTリクエストでアプリケーションにデータを送信するために押すために、テキスト領域の下に送信ボタンを追加します。

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

次に、 base.html 追加するファイル New Note ナビゲーションバーへのボタン:

  1. nano templates/base.html

次のように、強調表示されたコードでファイルを編集します。

フラスコノート/テンプレート/base.html
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

    <title>{% block title %} {% endblock %}</title>
  </head>
  <body>
    <nav class="navbar navbar-expand-md navbar-light bg-light">
        <a class="navbar-brand" href="{{ url_for('index')}}">FlaskNotes</a>
        <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
            <ul class="navbar-nav">
            <li class="nav-item active">
                <a class="nav-link" href="#">About</a>
            </li>

            <li class="nav-item active">
                <a class="nav-link" href="{{ url_for('create') }}">New Note</a>
           </li>
            </ul>
        </div>
    </nav>
    <div class="container">
        {% for message in get_flashed_messages() %}
            <div class="alert alert-danger">{{ message }}</div>
        {% endfor %}
        {% block content %} {% endblock %}
    </div>

    <!-- Optional JavaScript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  </body>
</html>

新しいを追加します <li> ナビゲーションバーへのアイテム url_for() リンクする関数 create() ビュー機能。 これにより、ナビゲーションバーから新しいメモを作成するためのページにアクセスできます。

まだ実行していない場合は、開発サーバーを実行します。

  1. flask run

ブラウザを使用して http://127.0.0.1:5000/create 次のマークダウンノートを追加します。

### Flask
Flask is a **web** framework for _Python_.

Here is the Flask logo:

![Flask Logo](https://flask.palletsprojects.com/en/1.1.x/_images/flask-logo.png)

この値下げには、 h3 見出し、単語 web 太字で、単語 Python イタリック体、および画像。

メモを送信すると、アプリケーションがそれをHTMLにフォーマットしていることがわかります。

これで、ユーザーがデータベースに新しいメモを追加できる新しいルートができました。 ユーザーはMarkdown形式でメモを取ることができ、アプリケーションはインデックスページにHTMLでメモを表示します。

このリポジトリからアプリケーションの完全なコードにアクセスできます。

結論

マークダウン形式でメモを取るためのFlaskアプリケーションを作成しました。これにより、ユーザーは見出し、太字、斜体のテキストなどのテキスト形式を使用したり、画像やリンクを追加したりできます。 アプリケーションをSQLiteデータベースに接続して、データを保存および取得しました。 マークダウンテキストをHTML変換に組み込んで、メモがページに表示されるようにしました。 PythonでのMarkdownの使用の詳細については、Pythonを使用する方法-Markdownを使用してMarkdownテキストをHTMLに変換するを参照してください。

Flaskの詳細については、次のチュートリアルを確認してください。