テンプレート Templates

アプリケーションの認証のviewは書きましたが、もしサーバを実行して試しにどのURLへ行っても、TemplateNotFoundエラーを見ることになるでしょう。それはviewがrender_template()を呼び出していても、まだテンプレートを書いていないためです。テンプレートファイルはflaskrパッケージ内のtemplatesディレクトリに格納されていきます。 You've written the authentication views for your application, but if you're running the server and try to go to any of the URLs, you'll see a ``TemplateNotFound`` error. That's because the views are calling :func:`render_template`, but you haven't written the templates yet. The template files will be stored in the ``templates`` directory inside the ``flaskr`` package.

テンプレートは、静的データと動的データのためのプレースホルダとを同様に含んでいるファイルです。テンプレートは最終ドキュメントを作成するために特定のデータと一緒に変換(render)されます。Flaskはテンプレートの変換にテンプレートライブラリのJinjaを使用します。 Templates are files that contain static data as well as placeholders for dynamic data. A template is rendered with specific data to produce a final document. Flask uses the `Jinja`_ template library to render templates.

この(チュートリアルの)アプリケーションでは、ユーザのブラウザに表示するHTMLへ変換(render)するためにテンプレートを使用していきます。Flaskでは、HTMLテンプレートの中で変換されるあらゆるデータを自動エスケープするように、Jinjaが設定されています。これは、ユーザが入力したものを安全に表示できるということです; <>のような、HTMLに干渉しかねない文字が入力されたとしても、望んでいない作用を引き起こさずに、ブラウザの中では同じように見える安全な値へとエスケープします。 In your application, you will use templates to render `HTML`_ which will display in the user's browser. In Flask, Jinja is configured to *autoescape* any data that is rendered in HTML templates. This means that it's safe to render user input; any characters they've entered that could mess with the HTML, such as ``<`` and ``>`` will be *escaped* with *safe* values that look the same in the browser but don't cause unwanted effects.

Jinjaは大部分でPythonのように見え、振る舞います。特別な区切り文字(delimiter)がテンプレートの中の静的データとJinja文法を区別するために使われます。{{}}の間のすべてのものが、最終ドキュメントへ出力される式(expression)になります。{%%}は、ifforのような制御フロー文(control flow statement)を示します。ブロック内の静的テキストがインデントを変えかねないので、Pythonとは異なり、ブロックはインデントではなく開始および終了タグで示されます。 Jinja looks and behaves mostly like Python. Special delimiters are used to distinguish Jinja syntax from the static data in the template. Anything between ``{{`` and ``}}`` is an expression that will be output to the final document. ``{%`` and ``%}`` denotes a control flow statement like ``if`` and ``for``. Unlike Python, blocks are denoted by start and end tags rather than indentation since static text within a block could change indentation.

ベースレイアウト(The Base Layout) The Base Layout

アプリケーションの各ページは、違う本体(body)を取り囲む同じベーシックレイアウトを持ちます。各テンプレートで全てのHTML構造を書く代わりに、各テンプレートはベースのテンプレートを拡張して、特定のセクションを上書きします。 Each page in the application will have the same basic layout around a different body. Instead of writing the entire HTML structure in each template, each template will *extend* a base template and override specific sections.

flaskr/templates/base.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を手作業で(テンプレートの中に)書く代わりに、viewに対応するURLを生成するために使用されます。 :data:`g` is automatically available in templates. Based on if ``g.user`` is set (from ``load_logged_in_user``), either the username and a log out link are displayed, or links to register and log in are displayed. :func:`url_for` is also automatically available, and is used to generate URLs to views instead of writing them out manually.

ページのtitleの後、そしてcontentの前に、このテンプレートはget_flashed_messages()から返される各メッセージ上をループします。エラーを表示するためにviewの中でflash()を使用しており、それ(viewの中でflashを使ったエラーメッセージ)を表示するコードがこれ(テンプレート中のget_flashed_messages)になります。 After the page title, and before the content, the template loops over each message returned by :func:`get_flashed_messages`. You used :func:`flash` in the views to show error messages, and this is the code that will display them.

ここでは、他のテンプレートで上書きされる予定の3つのブロックが定義されています: There are three blocks defined here that will be overridden in the other templates:

  1. {% block title %}は、ブラウザのタブおよびウィンドウのタイトルで表示されるタイトルを変更します。 ``{% block title %}`` will change the title displayed in the browser's tab and window title.

  2. {% block header %}titleと似ていますが、ページ上に表示されるタイトルを変更します。 ``{% block header %}`` is similar to ``title`` but will change the title displayed on the page.

  3. {% block content %}は、ログインformやブログの投稿記事など、各ページのコンテンツが行くところです。 ``{% block content %}`` is where the content of each page goes, such as the login form or a blog post.

ベースのテンプレート(訳注: 上で示したbase.html)はtemplatesディレクトリに直接置かれます。その他を編成された状態に保つため、blueprintのテンプレートは(templatesの下の)blueprintと同じ名前のディレクトリに置かれます。 The base template is directly in the ``templates`` directory. To keep the others organized, the templates for a blueprint will be placed in a directory with the same name as the blueprint.

登録(Register) Register

flaskr/templates/auth/register.html
{% 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へ伝えます。表示される全てのcontentは、ベースのテンプレートのブロックを上書きする、{% block %}タグの内側で現れる必要があります。 ``{% extends 'base.html' %}`` tells Jinja that this template should replace the blocks from the base template. All the rendered content must appear inside ``{% block %}`` tags that override blocks from the base template.

{% block title %}{% block header %}の内側に置くのは、ここで使われている便利なパターンです。これは、ウィンドウとページが同じタイトルを2回書くことなく共有できるように、タイトルのブロックを設定し、それからそのタイトルの値をヘッダのブロックの中に出力します。 A useful pattern used here is to place ``{% block title %}`` inside ``{% block header %}``. This will set the title block and then output the value of it into the header block, so that both the window and page share the same title without writing it twice.

inputタグは、ここではrequired属性を使用しています。これはブラウザに、それらの入力欄が記入されないうちは、formを提出(submit)しないように伝えます。もしその属性をサポートしない古いブラウザをユーザが使用している場合は、もしくは、リクエストの作成にブラウザ以外の何かをユーザが使用している場合は、まだFlaskのviewでデータを検証したいでしょう。サーバ側で常に網羅的に検証することは、クライアント側で何かしらの検証を同様に行うとしても、重要です。 The ``input`` tags are using the ``required`` attribute here. This tells the browser not to submit the form until those fields are filled in. If the user is using an older browser that doesn't support that attribute, or if they are using something besides a browser to make requests, you still want to validate the data in the Flask view. It's important to always fully validate the data on the server, even if the client does some validation as well.

ログイン Log In

タイトルと提出(submit)ボタン以外は、これは登録のテンプレートと同じです。 This is identical to the register template except for the title and submit button.

flaskr/templates/auth/login.html
{% 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 %}

ユーザ登録 Register A User

この時点で認証のテンプレートは書けたので、ユーザを登録可能です。サーバがまだ起動している(していなければflask runしてください)ことを確認してから、https://127.0.0.1:5000/auth/registerへ行ってください。 Now that the authentication templates are written, you can register a user. Make sure the server is still running (``flask run`` if it's not), then go to http://127.0.0.1:5000/auth/register.

試しにformを記入せずに「Register」ボタンを押すと、ブラウザがエラーメッセージを表示することが確認できます。試しにrequired属性をregister.htmlテンプレートから削除してから「Register」をもう一度クリックしてください。ブラウザがエラーを表示する代わりに、ページを再読み込みしてから、viewの中のflash()から来るエラーが表示されます。 Try clicking the "Register" button without filling out the form and see that the browser shows an error message. Try removing the ``required`` attributes from the ``register.html`` template and click "Register" again. Instead of the browser showing an error, the page will reload and the error from :func:`flash` in the view will be shown.

ユーザ名とパスワードを記入するとログインページにリダイレクトされます。試しに、不正なユーザ名を入力するか、正しいユーザ名と不正なパスワードを入力してください。もしログインすれば、まだリダイレクト先のindexのviewがないためにエラーになります。 Fill out a username and password and you'll be redirected to the login page. Try entering an incorrect username, or the correct username and incorrect password. If you log in you'll get an error because there's no ``index`` view to redirect to yet.

静的ファイルへ続きます。 Continue to :doc:`static`.