<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Flask | hgrs&#039;s Blog</title>
	<atom:link href="/archives/tag/flask/feed" rel="self" type="application/rss+xml" />
	<link>/</link>
	<description>文字好きエンジニアの技術メモ</description>
	<lastBuildDate>Sun, 26 May 2019 17:03:25 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.3.1</generator>

<image>
	<url>/wp-content/uploads/2019/05/cropped-port_512-32x32.png</url>
	<title>Flask | hgrs&#039;s Blog</title>
	<link>/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Flask チュートリアル</title>
		<link>/archives/297.html</link>
					<comments>/archives/297.html#comments</comments>
		
		<dc:creator><![CDATA[hgrs]]></dc:creator>
		<pubDate>Sun, 26 May 2019 17:03:25 +0000</pubDate>
				<category><![CDATA[技術メモ]]></category>
		<category><![CDATA[Flask]]></category>
		<category><![CDATA[Python]]></category>
		<guid isPermaLink="false">/?p=297</guid>

					<description><![CDATA[はじめに Webアプリケーションを簡単に作ることができるPython製のWebアプリケーションフレー...]]></description>
										<content:encoded><![CDATA[<h2>はじめに</h2>
<p>Webアプリケーションを簡単に作ることができるPython製のWebアプリケーションフレームワークのFlaskの使い方を簡単に見ていくチュートリアルです。</p>
<h2>目次</h2>
<ul>
<li><a href="#準備編">準備編</a></li>
<li><a href="#基本設定">基本設定</a></li>
<li><a href="#HTMLレンダリング">HTMLレンダリング</a></li>
<li><a href="#ルーティング">ルーティング</a></li>
<li><a href="#URL変数">URL変数</a></li>
<li><a href="#GET">GET</a></li>
<li><a href="#POST">POST</a></li>
</ul>
<h2>準備編<span id="準備編"></span></h2>
<h3>Flaskについて</h3>
<p>まずはFlaskについて知らなければ何も始まりません。</p>
<p>FlaskはWebアプリケーションフレームワークなので、Webアプリケーションを作ることができます。サイトは<a href="http://flask.pocoo.org/">こちら</a>です。</p>
<p>PythonのWebアプリケーションフレームワークはDjangoが有名ですが、比較的大規模向けで、シングルページのWebアプリケーションや、DBを使わないようなWebアプリケーションには対しては少し冗長な気がします。</p>
<p>それに対してFlaskは小規模な開発に対して学習コストが低く、簡易的なWebアプリケーションであれば、すぐに動作します。なので僕はよくFlaskを使います。</p>
<h3>インストール</h3>
<p>Flaskはpip経由でインストールできます。</p>
<pre><code class="language-bash">$ pip install flask</code></pre>
<p>簡単ですね。</p>
<h3>この記事で使うファイル</h3>
<p>ファイル内容は全て記事内に書くので、記事をコピペしていっても動作はするようにします。なお、それぞれのコードの1行目にパスとファイル名を書こうと思います。</p>
<h2>基本設定<span id="基本設定"></span></h2>
<h3>Webサーバ起動</h3>
<p>とりあえず動かしてみて、どのような記述をし、どのように起動をするのか確認してみましょう。</p>
<p>こちらがコードです。</p>
<pre><code class="language-python"># ./main.py
from flask import Flask

app = Flask(__name__)

@app.route(&#039;/&#039;)
def index():
    return &#039;Hello, world!&#039;

if __name__ == &#039;__main__&#039;:
    app.run()</code></pre>
<p>普通に<code>python main.py</code>で実行するとWebサーバが立ち上がり、<a href="http://127.0.0.1:5000/">http://127.0.0.1:5000/</a>にアクセスすると<code>Hello, world!</code>と表示されます！</p>
<p>では、それぞれの設定を見ていきましょう。</p>
<h3>アドレス変更（外部公開）</h3>
<p>先ほどのアドレスが<code>http://127.0.0.1:5000/</code>となっていることからわかるように、初期設定ではローカルでサーバが立ち上がるようになっています。</p>
<p>これを他アドレス、例えば外部公開（<code>0.0.0.0</code>）にするには<code>run</code>に対して、<code>host</code>を引数として与えます。次のような感じです。</p>
<pre><code class="language-python">app.run(host=&#039;0.0.0.0&#039;)</code></pre>
<p>これで、外部からアクセスできるようになりました。</p>
<h3>ポート変更</h3>
<p>ポートの変更も<code>run</code>に引数を与えることで指定できます。例えば次のような感じです。</p>
<pre><code class="language-python">app.run(port=80)</code></pre>
<h3>同時アクセス対応</h3>
<p>多数アクセスに対して並列処理を行うには並列処理機能をオンにしなければなりません。こちらも<code>run</code>に引数を与えます。</p>
<pre><code class="language-python">app.run(threaded=True)</code></pre>
<h3>デバッグモード</h3>
<p>編集を加えるたびにいちいちサーバを再起動するのは面倒です。そこで、デバックモードを使うことで、サーバを立てたまま編集が可能になります。こちらも<code>run</code>に引数を与えます。</p>
<pre><code class="language-python">app.run(debug=True)</code></pre>
<p>今回の記事内では間違いをすぐ修正できるように、常にこのデバッグモードにしておきますが、適宜自分で変更してください。</p>
<h2>HTMLレンダリング<span id="HTMLレンダリング"></span></h2>
<h3>変数埋め込み</h3>
<p>ただ<code>Hello, world!</code>と表示されてもつまらないので、普通のHTMLをレンダリングしてみましょう。</p>
<p>使用するHTMLはこちらです。</p>
<pre><code class="language-html">&lt;!-- ./templates/index.html --&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot;&gt;
  &lt;title&gt;Flaskチュートリアル&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;p&gt;{{ message }}&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>まず、保存するディレクトリに注意してください。Flaskで使うHTMLは<code>templates</code>に、CSSや画像のリソースは<code>static</code>に保存します。こちらは設定で変えることもできますが、それはまたの機会に。</p>
<p>また<code>body</code>を見ると見慣れない<code>{{ message }}</code>という囲いがありますね。こちら、Flask側から変数を埋め込むためのプレースホルダです。</p>
<p>では、次にFlaskのファイルです。</p>
<pre><code class="language-python"># ./main.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route(&#039;/&#039;)
def index():
    message = &#039;Hello, world!&#039;
    return render_template(&#039;index.html&#039;, message=message)

if __name__ == &#039;__main__&#039;:
    app.run(debug=True)</code></pre>
<p>先ほどと比べ<code>render_template</code>が増えました。この関数により、HTMLにあったプレースホルダを埋めた状態のHTMLを得ることができます。</p>
<p><code>render_template</code>は第1引数にHTMLファイル名、プレースホルダにつけた名前のキーワード引数に埋め込む内容を渡します。</p>
<p>この例では<code>Hello, world!</code>と入れた変数を渡しているので、結局<code>Hello, world!</code>と表示されるだけですね笑。</p>
<h3>繰り返し表示（for文）</h3>
<p><code>render_template</code>では数値や文字列だけでなく、配列を渡し、HTML内でfor文を書くこともできます。</p>
<p>こちらが例です。</p>
<pre><code class="language-html">&lt;!-- ./templates/index.html --&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot;&gt;
  &lt;title&gt;Flaskチュートリアル&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  {% for name in names %}
    &lt;p&gt;{{ name }}&lt;/p&gt;
  {% endfor %}
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<pre><code class="language-python"># ./main.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route(&#039;/&#039;)
def index():
    names = [&#039;Alice&#039;, &#039;Bob&#039;, &#039;Carol&#039;]
    return render_template(&#039;index.html&#039;, names=names)

if __name__ == &#039;__main__&#039;:
    app.run(debug=True)</code></pre>
<p>これで、3人の名前が表示されたはずです。これを使えば様々な活用ができますね！</p>
<h3>条件付き表示（if文）</h3>
<p>for文が使えるように、HTML内でif文も使えます。</p>
<p>こちらが例です。</p>
<pre><code class="language-html">&lt;!-- ./templates/index.html --&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot;&gt;
  &lt;title&gt;Flaskチュートリアル&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  {% if message %}
    &lt;p&gt;{{ message }}&lt;/p&gt;
  {% else %}
    &lt;p&gt;No Message.&lt;/p&gt;
  {% endif %}
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<pre><code class="language-python"># ./main.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route(&#039;/&#039;)
def index():
    return render_template(&#039;index.html&#039;)

if __name__ == &#039;__main__&#039;:
    app.run(debug=True)</code></pre>
<p>この例では<code>message</code>が存在していないので、<code>else</code>に回り<code>No Message.</code>と表示されます。</p>
<h3>他のHTMLを埋め込み</h3>
<p>例えばHTMLの<code>head</code>やコンテンツの一部を共有する場合に、他のHTMLに別のHTMLを埋め込むこともできます。</p>
<p>こちらが例です。</p>
<pre><code class="language-html">&lt;!-- ./templates/layout.html --&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot;&gt;
  &lt;title&gt;Flaskチュートリアル&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;p&gt;{{ layout_message }}&lt;/p&gt;
  {% block body %}{% endblock %}
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<pre><code class="language-html">&lt;!-- ./templates/index.html --&gt;
{% extends &quot;layout.html&quot; %}
{% block body %}
  &lt;p&gt;{{ index_message }}&lt;/p&gt;
{% endblock %}</code></pre>
<pre><code class="language-python"># ./main.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route(&#039;/&#039;)
def index():
    index_message = &#039;Here is INDEX.&#039;
    layout_message = &#039;Here is LAYOUT.&#039;
    return render_template(&#039;index.html&#039;,
                           index_message=index_message,
                           layout_message=layout_message)

if __name__ == &#039;__main__&#039;:
    app.run(debug=True)</code></pre>
<p>こちらは<code>layout.html</code>の中に<code>index.html</code>を埋め込んでいます。また変数の埋め込みはどちらのHTMLに対してもできるので、どんどん拡張していけます。</p>
<h2>ルーティング<span id="ルーティング"></span></h2>
<p>そろそろシングルページは飽きてきましたね。</p>
<p>他のルートも作ってみましょう。実は、先ほどからずっと出てきている<code>@app.route(&#039;/&#039;)</code>というデコレータを変更することで、ルートを変更できます。</p>
<p>こちらが例です。</p>
<pre><code class="language-python"># ./main.py
from flask import Flask

app = Flask(__name__)

@app.route(&#039;/&#039;)
def index():
    return &#039;index&#039;

@app.route(&#039;/1&#039;)
def page_1():
    return &#039;page1&#039;

@app.route(&#039;/2&#039;)
def page_2():
    return &#039;page2&#039;

if __name__ == &#039;__main__&#039;:
    app.run(debug=True)</code></pre>
<p>これで、<code>http://127.0.0.1:5000/</code>にアクセスすると<code>index</code>、<code>http://127.0.0.1:5000/1</code>にアクセスすると<code>page1</code>、<code>http://127.0.0.1:5000/2</code>にアクセスすると<code>page2</code>と表示されます。</p>
<p>簡単ですね。</p>
<h2>URL変数<span id="URL変数"></span></h2>
<p>先ほどのルーティングの例では単純に<code>/1</code>で<code>page1</code>、<code>/2</code>で<code>page2</code>と表示されますね。これを100ページまで作りたいとなった時に、全てなんて作ってられません。</p>
<p>そこで、URLから変数を得ることができます。</p>
<p>こちらが例です。</p>
<pre><code class="language-python"># ./main.py
from flask import Flask

app = Flask(__name__)

@app.route(&#039;/&#039;)
def index():
    return &#039;index&#039;

@app.route(&#039;/&lt;number&gt;&#039;)
def page(number):
    return f&#039;page{number}&#039;

if __name__ == &#039;__main__&#039;:
    app.run(debug=True)</code></pre>
<p>ルートに<code>&lt;変数名&gt;</code>を入れ、関数の引数として指定すると、URLから値を受け取ることができます。</p>
<p>こうすることで、どのような入力が来てもページを生成することができます。</p>
<p>（f-stringsを使用しているのでPythonが3.6未満の人は<code>f&#039;page{number}&#039;</code>を<code>&#039;page&#039;+numbar</code>とかにしてください。）</p>
<h2>GET<span id="GET"></span></h2>
<p>さあURLで変数を指定できるだけでは微妙です。<code>GET</code>でデータを受け取ってみましょう。</p>
<p>こちらが例です。</p>
<pre><code class="language-html">&lt;!-- ./templates/index.html --&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot;&gt;
  &lt;title&gt;Flaskチュートリアル&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;form action=&quot;/receive&quot; method=&quot;GET&quot;&gt;
    &lt;input type=&quot;text&quot; name=&quot;text&quot;&gt;
    &lt;button type=&quot;submit&quot;&gt;送信&lt;/button&gt;
  &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<pre><code class="language-python"># ./main.py
from flask import Flask, request, render_template

app = Flask(__name__)

@app.route(&#039;/&#039;)
def index():
    return render_template(&#039;index.html&#039;)

@app.route(&#039;/receive&#039;)
def receive():
    return request.args.get(&#039;text&#039;)

if __name__ == &#039;__main__&#039;:
    app.run(debug=True)</code></pre>
<p>送信を押したらそのまま表示される何でもない活用方法ですが、<code>GET</code>で受け取った変数は<code>request.args.get</code>で名前を指定することで受け散ることができます。</p>
<h2>POST<span id="POST"></span></h2>
<p><code>GET</code>をやったなら次は<code>POST</code>です。</p>
<p>こちらが例です。</p>
<pre><code class="language-html">&lt;!-- ./templates/index.html --&gt;
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
  &lt;meta charset=&quot;utf-8&quot;&gt;
  &lt;title&gt;Flaskチュートリアル&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
  &lt;form action=&quot;/receive&quot; method=&quot;POST&quot;&gt;
    &lt;input type=&quot;text&quot; name=&quot;text&quot;&gt;
    &lt;button type=&quot;submit&quot;&gt;送信&lt;/button&gt;
  &lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;</code></pre>
<pre><code class="language-python"># ./main.py
from flask import Flask, request, render_template

app = Flask(__name__)

@app.route(&#039;/&#039;)
def index():
    return render_template(&#039;index.html&#039;)

@app.route(&#039;/receive&#039;, methods=[&#039;GET&#039;, &#039;POST&#039;])
def receive():
    if request.method == &#039;POST&#039;:
        return request.form[&#039;text&#039;]
    return &#039;Not POST.&#039;

if __name__ == &#039;__main__&#039;:
    app.run(debug=True)</code></pre>
<p><code>POST</code>は<code>POST</code>であることをルートのところで明示しなければなりません。受け取りは<code>request.form</code>に入っています。これは辞書型のような形式になっているの、それぞれの名前から値を引き出せます。</p>
<h2>おわりに</h2>
<p>1記事にまとめようとしたら、馬鹿みたいに長くなりました笑。</p>
<p>追記するようなことがあれば、どんどん足していくので、もし書いて欲しいことがあればコメントとかください。</p>
]]></content:encoded>
					
					<wfw:commentRss>/archives/297.html/feed</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
	</channel>
</rss>
