Pythonの使用方法-FlaskとSQLiteでMarkdown
序章
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をインストールします。 次に、メモを保存するために使用するデータベースを作成し、それにサンプルデータを追加します。
まず、プログラミング環境をまだアクティブにしていない場合はアクティブにします。
- source env/bin/activate
プログラミング環境をアクティブにしたら、次のコマンドを使用してFlaskとPython-Markdownライブラリをインストールします。
- pip install flask markdown
次に、というデータベーススキーマファイルを作成します schema.sql
、を作成するためのSQLコマンドが含まれます notes
テーブル。 内のファイルを開きます flask_notes
ディレクトリ:
- nano schema.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.py
中 flask_notes
ディレクトリ:
- nano 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()メソッドのプレースホルダーであり、メモの内容を含むタプルを渡して、データベースにデータを安全に挿入します。
最後に、変更をコミットして接続を閉じます。
ファイルを保存して閉じます。
プログラムを実行します。
- python init_db.py
実行後、という新しいファイル database.db
あなたに表示されます flask_notes
ディレクトリ。
環境をアクティブ化し、FlaskとPython-Markdownをインストールし、SQLiteデータベースを作成しました。 次に、データベースからMarkdownノートを取得し、HTMLに変換して、アプリケーションのホームページに表示します。
ステップ2—インデックスページにメモを表示する
このステップでは、データベースに接続し、データベースにあるサンプルデータを表示するFlaskアプリケーションを作成します。 データベース内のマークダウンテキストをHTMLに変換してから、インデックスページにレンダリングします。
まず、を作成します app.py
あなたの中のアプリケーションファイル flask_notes
ディレクトリ:
- nano 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 = Flask(__name__)
app.config['SECRET_KEY'] = 'this should be a secret random string'
ここでは、Flaskアプリケーションオブジェクトを作成し、秘密鍵をセキュアセッションに設定します。
次に、次のコードを追加します。
#. . .
@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
リスト。
すべての追加後、ファイルは次のようになります。
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
その中:
- mkdir templates
- nano templates/base.html
中に次のコードを追加します base.html
; ここではBootstrapを使用していることに注意してください。 FlaskのHTMLテンプレートに慣れていない場合は、 Python3でFlaskを使用してWebアプリケーションを作成する方法のステップ3をお読みください。
<!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
ファイル:
- nano templates/index.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が必要とする環境変数を設定し、次のコマンドを使用してアプリケーションを実行します。
- export FLASK_APP=app
- export FLASK_ENV=development
- 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
新しいルートを追加するファイル:
- nano 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
テンプレートファイル:
- nano templates/create.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
ナビゲーションバーへのボタン:
- nano templates/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()
ビュー機能。 これにより、ナビゲーションバーから新しいメモを作成するためのページにアクセスできます。
まだ実行していない場合は、開発サーバーを実行します。
- 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の詳細については、次のチュートリアルを確認してください。