テンプレート
アプリケーションの認証ビューを作成しましたが、サーバーを実行しているときにいずれかのURLにアクセスしようとすると、TemplateNotFound
エラーが表示されます。 これは、ビューがrender_template()
を呼び出しているが、テンプレートをまだ作成していないためです。 テンプレートファイルは、flaskr
パッケージ内のtemplates
ディレクトリに保存されます。
テンプレートは、静的データと動的データのプレースホルダーを含むファイルです。 テンプレートは、最終的なドキュメントを作成するために特定のデータでレンダリングされます。 Flaskは、 Jinja テンプレートライブラリを使用してテンプレートをレンダリングします。
アプリケーションでは、テンプレートを使用して HTML をレンダリングします。これはユーザーのブラウザーに表示されます。 Flaskでは、JinjaはHTMLテンプレートでレンダリングされるすべてのデータを autoescape するように構成されています。 これは、ユーザー入力を安全にレンダリングできることを意味します。 <
や>
など、入力した文字がHTMLを混乱させる可能性がある場合は、エスケープされ、安全の値は同じになります。ブラウザで、しかし望ましくない効果を引き起こさないでください。
Jinjaは、ほとんどPythonのように見えて動作します。 Jinja構文をテンプレート内の静的データと区別するために、特別な区切り文字が使用されます。 {{
と}}
の間はすべて、最終的なドキュメントに出力される式です。 {%
および%}
は、if
およびfor
のような制御フローステートメントを示します。 Pythonとは異なり、ブロック内の静的テキストはインデントを変更する可能性があるため、ブロックはインデントではなく開始タグと終了タグで示されます。
基本レイアウト
アプリケーションの各ページは、異なる本文の周りに同じ基本レイアウトを持ちます。 各テンプレートにHTML構造全体を書き込む代わりに、各テンプレートは基本テンプレートを拡張し、特定のセクションをオーバーライドします。
<!doctype html>
<title>{% block title %}{% endblock %} - Flaskr</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
<nav>
<h1>Flaskr</h1>
<ul>
{% if g.user %}
<li><span>{{ g.user['username'] }}</span>
<li><a href="{{ url_for('auth.logout') }}">Log Out</a>
{% else %}
<li><a href="{{ url_for('auth.register') }}">Register</a>
<li><a href="{{ url_for('auth.login') }}">Log In</a>
{% endif %}
</ul>
</nav>
<section class="content">
<header>
{% block header %}{% endblock %}
</header>
{% for message in get_flashed_messages() %}
<div class="flash">{{ message }}</div>
{% endfor %}
{% block content %}{% endblock %}
</section>
g はテンプレートで自動的に使用可能になります。 g.user
が設定されているかどうかに基づいて(load_logged_in_user
から)、ユーザー名とログアウトリンクのいずれかが表示されます。それ以外の場合は、登録とログインへのリンクが表示されます。 url_for()
も自動的に使用可能になり、ビューを手動で書き出す代わりに、ビューへのURLを生成するために使用されます。
ページタイトルの後、コンテンツの前で、テンプレートはget_flashed_messages()
によって返される各メッセージをループします。 ビューでflash()
を使用してエラーメッセージを表示しました。これは、エラーメッセージを表示するコードです。
ここで定義されている3つのブロックは、他のテンプレートで上書きされます。
{% block title %}
は、ブラウザのタブに表示されるタイトルとウィンドウのタイトルを変更します。{% block header %}
はtitle
に似ていますが、ページに表示されるタイトルが変更されます。{% block content %}
は、ログインフォームやブログ投稿など、各ページのコンテンツが表示される場所です。
基本テンプレートは、templates
ディレクトリに直接あります。 他のテンプレートを整理するために、ブループリントのテンプレートは、ブループリントと同じ名前のディレクトリに配置されます。
登録
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Register{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post">
<label for="username">Username</label>
<input name="username" id="username" required>
<label for="password">Password</label>
<input type="password" name="password" id="password" required>
<input type="submit" value="Register">
</form>
{% endblock %}
{% extends 'base.html' %}
は、このテンプレートがベーステンプレートのブロックを置き換える必要があることをJinjaに通知します。 レンダリングされたすべてのコンテンツは、ベーステンプレートのブロックをオーバーライドする{% block %}
タグ内に表示される必要があります。
ここで使用する便利なパターンは、{% block title %}
を{% block header %}
の中に配置することです。 これにより、タイトルブロックが設定され、その値がヘッダーブロックに出力されるため、ウィンドウとページの両方が2回書き込むことなく同じタイトルを共有します。
input
タグは、ここでrequired
属性を使用しています。 これは、これらのフィールドに入力されるまでフォームを送信しないようにブラウザに指示します。 ユーザーがその属性をサポートしていない古いブラウザーを使用している場合、またはブラウザー以外のものを使用してリクエストを行っている場合でも、Flaskビューでデータを検証する必要があります。 クライアントが何らかの検証を行ったとしても、サーバー上のデータを常に完全に検証することが重要です。
ログインする
これは、タイトルと送信ボタンを除いて、登録テンプレートと同じです。
{% extends 'base.html' %}
{% block header %}
<h1>{% block title %}Log In{% endblock %}</h1>
{% endblock %}
{% block content %}
<form method="post">
<label for="username">Username</label>
<input name="username" id="username" required>
<label for="password">Password</label>
<input type="password" name="password" id="password" required>
<input type="submit" value="Log In">
</form>
{% endblock %}
ユーザーを登録する
認証テンプレートが作成されたので、ユーザーを登録できます。 サーバーがまだ実行されていることを確認し(実行されていない場合はflask run
)、 http://127.0.0.1:5000/auth/registerに移動します。
フォームに記入せずに「登録」ボタンをクリックしてみてください。ブラウザにエラーメッセージが表示されることを確認してください。 register.html
テンプレートからrequired
属性を削除して、もう一度[登録]をクリックしてみてください。 ブラウザにエラーが表示される代わりに、ページがリロードされ、ビューのflash()
からのエラーが表示されます。
ユーザー名とパスワードを入力すると、ログインページにリダイレクトされます。 間違ったユーザー名、または正しいユーザー名と間違ったパスワードを入力してみてください。 ログインすると、リダイレクト先のindex
ビューがまだないため、エラーが発生します。
静的ファイルに進みます。