blog.miguelgrinberg.com
ミゲル・グリンバーグ
<<<前 次>>>
この記事は、Miguel Greenbergによる教科書の新版の第2部の翻訳であり、著者はこの出版物を2018年5月に完成させる予定です。
私の側では、翻訳についていくつもりです。
Flask Mega-Tutorialシリーズのこの2回目の記事では、テンプレートの操作方法について説明します。
参考までに、以下はこのシリーズの記事のリストです。
注1:このコースの古いバージョンをお探しの場合は、こちらをご覧ください 。
注2:突然、このブログの私の(ミゲル)の仕事を支持して声を上げたい場合、または単に記事を1週間待つ忍耐がない場合、私(ミゲルグリーンバーグ)はこのガイドの完全版にパッケージ化された電子書籍またはビデオを提供します。 詳細については、 learn.miguelgrinberg.comをご覧ください 。
短い繰り返し
第1章を完了すると、次のファイル構造を備えた完全に機能するシンプルなWebアプリケーションが作成されます。
microblog\ venv\ app\ __init__.py routes.py microblog.py
アプリケーションを実行するには、ターミナルセッションでFLASK_APP=microblog.py
を設定してから、 FLASK_APP=microblog.py
を実行します。 http://localhost:5000
/ URLをWebブラウザーのアドレスバーに入力することで開くことができるアプリケーションでWebサーバーを起動します。
この章では、引き続き同じアプリケーションで作業します。特に、より洗練された構造と多くの動的コンポーネントを持つより複雑なWebページを作成する方法を学習します。 アプリケーションまたは開発のワークフローについて不明な点がある場合は、続行する前に第1章を確認してください。
この章のGitHubリンク: Browse 、 Zip 、 Diff 。
パターンとは何ですか?
マイクロブログアプリのホームページのタイトルページにユーザーを迎えたい。 とりあえず、アプリケーションにユーザーコンセプトがまだないという事実は無視します。これは後で行われるためです。 代わりに、次のように、Python辞書として実装する架空の(模擬)ユーザーを使用します。
user = {'username': 'Miguel'}
モックオブジェクトの作成は、まだ存在しないシステムの他の部分を心配することなく、アプリケーションの一部に集中できる便利な方法です。 アプリケーションのホームページを作成したいのですが、ユーザーシステムの欠如が気を散らせたくありません。 したがって、ユーザーオブジェクトを作成するだけです。
アプリケーションのビュー関数は、単純な文字列を返します。 次に、返されたこの文字列を完全なHTMLページに展開します。
from app import app @app.route('/') @app.route('/index') def index(): user = {'username': 'miguel'} return ''' <html> <head> <title>Home Page - Microblog</title> </head> <body> <h1>Hello, ''' + user['username'] + '''!</h1> </body> </html>'''
HTMLを初めて使用する場合は、ウィキペディアのマークアップHTMLを読んで簡単な紹介を読むことをお勧めします。
上記のように表示機能を更新し、ブラウザで確認します。

上記で使用したソリューションでは不十分であることに同意していただければ幸いです。 絶えず変化するユーザーからのブログ投稿を受け取ったときに、このビューでコードがどれほど複雑になるかを考えてください。 また、このアプリケーションには他のURLに関連付けられる表示機能が追加されるため、いつかこのアプリケーションのレイアウトを変更し、各ビューでHTMLを更新する必要がある場合を想像してください。 これは明らかに、アプリケーションの成長に合わせて拡張できるオプションではありません。
アプリケーションのロジックをWebページのレイアウトやプレゼンテーションとは別にしておけば、すべてがより良く整理されているでしょうか? Pythonでアプリケーションロジックをコーディングするときに、Webデザイナーを雇ってキラーWebサイトを作成することもできます。
テンプレートは、プレゼンテーションとビジネスロジックをこのように分離するのに役立ちます。 Flaskでは、テンプレートは、アプリケーションパッケージ内にあるtemplates
フォルダーに保存された個別のファイルとして書き込まれます。 したがって、 microblog
ディレクトリにいることを確認して、テンプレートを保存するディレクトリを作成します。
(venv) $ mkdir app/templates
または:
(venv) C:\microblog>mkdir app\templates
以下に、最初のテンプレートを見ることができます。これは、上記のindex()
ビュー関数によって返されるHTMLページと機能が似ています。 このファイルをapp/templates/index.html
書きます:
<html> <head> <title>{{ title }} - Microblog</title> </head> <body> <h1>Hello, {{ user.username }}!</h1> </body> </html>
これは標準の非常にシンプルなHTMLページです。 このページで唯一面白いのは、 {{...}}
セクションに囲まれた動的コンテンツのプレースホルダーがいくつかあることです。 これらのプレースホルダーは、変数であり、実行時にのみ決定されるページの部分を表します。
ページプレゼンテーションがHTMLテンプレートにアップロードされたので、表示機能を単純化できます(ファイル\ app \ routes.py ):
# -*- coding: utf-8 -*- from flask import render_template from app import app @app.route('/') @app.route('/index') def index(): user = {'username': 'Miguel'} return render_template('index.html', title='Home', user=user)
見た目が良くなりましたよね? このアプリの新しいバージョンを試して、テンプレートの動作を確認してください。 ページをブラウザにロードすると、HTMLソースコードを表示して、元のテンプレートと比較できます。
テンプレートを完全なHTMLページに変換する操作は、レンダリングと呼ばれます。 テンプレートを表示するには、 render_template()
と呼ばれるフラグフレームワークが付属する関数をインポートする必要がありました。 この関数は、テンプレートファイルの名前とテンプレートの変数引数リストを受け取り、同じテンプレートを返しますが、その中のすべてのプレースホルダーは実際の値に置き換えられます。
render_template()
関数は、Flaskに同梱されているJinja2
テンプレートJinja2
を呼び出します。 Jinja2
は、 {{...}}
ブロックをrender_template()
呼び出しで指定された引数で指定された対応する値に置き換えます。
条件付きステートメント
レンダリング中にJinja2
がプレースホルダーを実際の値で置き換えるのを見ましたが、これはテンプレートファイルでJinja2
がサポートする多くの強力な操作の1つにすぎません。 たとえば、テンプレートは{% ...%}
ブロック内で定義された制御ステートメントもサポートします。 index.html
テンプレートの次のバージョンは、条件式を追加します。
<html> <head> {% if title %} <title>{{ title }} - Microblog</title> {% else %} <title>Welcome to Microblog!</title> {% endif %} </head> <body> <h1>Hello, {{ user.username }}!</h1> </body> </html>
これでテンプレートが少しスマートになりました。 ビュー関数が、空のタイトルを表示する代わりに、変数の値をタイトルプレースホルダーに渡すのを忘れた場合、テンプレートはデフォルト値を提供します。 view関数(file \ app \ routes.py )のrender_template()
呼び出しでtitle引数を削除することにより、この条件がどのように機能するかを試すことができます。
サイクル
ログインしたユーザーは、おそらく接続されたユーザーからの最新のメッセージをホームページで見たいと思うでしょう。そこで、これをサポートするためにアプリケーションを拡張します。
繰り返しますが、私は偽のオブジェクトでトリックを使用して、いくつかのユーザーといくつかのメッセージを作成します:
# -*- coding: utf-8 -*- from flask import render_template from app import app @app.route('/') @app.route('/index') def index(): user = {'username': ' '} posts = [ { 'author': {'username': 'John'}, 'body': 'Beautiful day in Portland!' }, { 'author': {'username': 'Susan'}, 'body': 'The Avengers movie was so cool!' }, { 'author': {'username': ''}, 'body': ' !!' } ] return render_template('index.html', title='Home', user=user, posts=posts)
カスタム投稿を表すには、各アイテムがAuthor
フィールドとBody
フィールドを持つ辞書であるリストを使用します。 ユーザーとブログの投稿を実際に理解したら、これらのフィールド名を保存して、これらの一時オブジェクトを使用してホームページテンプレートを設計およびテストするために行ったすべての作業が実際のユーザーを紹介する場合でも引き続き機能するようにしますデータベースからのメッセージ。
テンプレート側では、新しい問題を解決する必要があります。 メッセージリストには、任意の数の要素を含めることができます。 ページにはいくつの投稿が表示されますか? テンプレートは、存在するレコードの数について推測することができないため、一般的な方法でビューを送信するのと同じ数のメッセージを表示する準備ができている必要があります。
このタイプの問題に対して、Jinja2は制御構造(ファイルapp / templates / index.html)を提供します:
<html> <head> {% if title %} <title>{{ title }} - Microblog</title> {% else %} <title>Welcome to Microblog</title> {% endif %} </head> <body> <h1>Hi, {{ user.username }}!</h1> {% for post in posts %} <div><p>{{ post.author.username }} says: <b>{{ post.body }}</b></p></div> {% endfor %} </body> </html>
シンプルでしょ? この新しいバージョンのアプリケーションを試してください。メッセージリストにさらにコンテンツを追加して、テンプレートがどのように適応し、プレゼンテーション機能によって送信されたすべてのメッセージを常に表示するかを確認してください。

翻訳者注:エンコーディングはそれほど単純ではありません。 グリーティングを
うとしましたが、エラーが発生しました。 index.htmlファイルのエンコードを確認します。 utf-8に保存する必要があります。

テンプレートの継承
ほとんどのWebアプリケーションには、ページ上部にナビゲーションバーがあり、プロファイル、ログイン、ログアウトなどを編集するためのリンクなど、一般的に使用されるリンクがいくつかあります。 HTMLを使用してindex.html
テンプレートにナビゲーションバーを簡単に追加できますが、アプリケーションが大きくなるにつれて、他のページにも同じナビゲーションバーが必要になります。 多くのHTMLテンプレートでナビゲーションバーの複数のコピーをサポートしたくありません。可能な場合は、コードを複製せずに行うことをお勧めします。
Jinja2には、この問題を具体的に解決するテンプレート継承関数があります。 基本的に、すべてのテンプレートに共通のページレイアウトの部分を、他のすべてのテンプレートの派生元のベーステンプレートに移動できます。
そのため、今、簡単なナビゲーションバーを含む基本的なbase.html
テンプレートと、以前に実装したヘッダーロジックを定義しています。 app/templates/base.html
次のテンプレートを書く必要がありapp/templates/base.html
:
<html> <head> {% if title %} <title>{{ title }} - Microblog</title> {% else %} <title>Welcome to Microblog</title> {% endif %} </head> <body> <div>Microblog: <a href="/index">Home</a></div> <hr> {% block content %}{% endblock %} </body> </html>
このテンプレートでは、ブロック制御ステートメントを使用して、派生テンプレートを挿入できる場所を決定しました。 ブロックには、派生テンプレートがコンテンツを提供するときに参照できる一意の名前が付けられます。
基本的なテンプレートを使用して、 base.html
から継承することでindex.html
を単純化できます。
{% extends "base.html" %} {% block content %} <h1>Hi, {{ user.username }}!</h1> {% for post in posts %} <div><p>{{ post.author.username }} says: <b>{{ post.body }}</b></p></div> {% endfor %} {% endblock %}
base.htmlテンプレートがページの全体的な構造を処理するようになったため、 index.htmlからこれらの要素をすべて削除し、コンテンツの一部のみを残しました。 extends
ステートメントは2つのテンプレート間に継承リンクを設定するため、 base.html
はindex.html
をレンダリングするように要求されたときにbase.html
に埋め込む必要があることをbase.html
ます。 2つのテンプレートにはcontent
という名前の一貫したblock
ステートメントがあります。これが、Jinja2が2つのテンプレートを1つに結合する方法を知っている方法です。 これで、アプリケーション用に追加のページを作成する必要がある場合、同じbase.html
テンプレートから派生テンプレートとして作成できます。これにより、同じように見え、重複することなく見えるアプリケーションのすべてのページを作成できます。

<<<前 次>>>