Help us understand the problem. What is going on with this article?

flaskのパスを指定する

はじめに

pythonのwebフレームワークとして有名なflaskについて多くのサイトで解説されていますが、自分のWEBの技術力ではかみ砕くのに苦労したため、ここで詳細に一つずつまとめます。
さらに、個人的にフォルダのパスを自分で決めたいタイプなのでそれの方法も記載します。

環境

  • python:3.6.5
  • flask:1.0.2

REST API チックなサーバを立てる

flaskでは、シンプルなREST APIチックなサーバを立てるのはとても簡単です。
Flaskクラスを生成してURL(のエンドポイント)を設定してあげて、runするだけです。

flask_main.py
from flask import Flask

app = Flask(__name__)

@app.route('/index')
def index():
    return "hello flask REST"

app.run()

実行

# python3 flask_main.py

 * Serving Flask app "flask_main" (lazy loading) * Environment: production
   WARNING: Do not use the development server in a production environment.   Use a production WSGI server instead. * Debug mode: off
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

実行後、ブラウザなりリクエストソフトなりでhttp://localhost:5000/index に接続するとhello flask RESTと表示されるはずです。
これで自分で立てたサーバにアクセスして文字列を取得することができました。
REST API チックに言うとGETメソッドのindexエンドポイントにリクエストを発行して、"hello flask REST"という文字列を取得できたとなります。

WEBサーバを立てる

WEBサーバには、当然ですが表示されるページ(html)が必要になります。
flaskでは、ユーザ -> python -> html -> ユーザのような流れで処理が進みます。
※さっきのREST APIではユーザ -> python -> ユーザでした。単純にhtmlが追加されただけです。
そのため、templates内にhtmlを配置してpythonでhtmlを呼び出す関数render_templateを追加してあげることで実現します。

ディレクトリ構成

root\
  |--templates\
  |   --index.html
  |--flask_main.py
flask_main.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/index')
def index():
    return render_template('index.html')


app.run()
index.html
<h1> HELLOW FLASK</h1>

実行後、ブラウザでhttp://localhost:5000/index に接続するとHELLO FLASKが太文字で表示されるはずです。
これで自分で立てたサーバにアクセスしてWEBページを取得することができました。

WEBページにCSSを適用する

WEBページを装飾するためには文字や背景のスタイルを定義したファイル(CSS)がある方が便利なので、昨今のWEBサーバには必須レベルでCSSが存在しています。
flaskは、staticフォルダに配置して、htmlファイルにurl_forや直打ちで指定してあげることで適用します。

ディレクトリ構成

root\
  |--static\
  |   --index.css
  |--templates\
  |   --index.html
  |--flask_main.py

pythonファイルは上と同じ

index.css
h1 {
    background-color: blue;
    color: white;
}
index.html
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='index.css') }}">
<h1> HELLOW FLASK</h1>

実行後、ブラウザでhttp://localhost:5000/index に接続するとHELLO FLASKの背景が青、文字が白で表示されるはずです。
これでWEBページにcssが適用できました。

WEBページにJavaScriptを適用する

WEBページはあくまでページなので日付の表示など動的な表現が苦手です。
そこで動的な表現をするためにJavaScriptが存在しています。
flaskではstaticの配下にJavaScriptを配置して、url_forを使用して設定します。

ディレクトリ構成

root\
  |--static\
  |   --index.css
  |   --index.js
  |--templates\
  |   --index.html
  |--flask_main.py

pythonファイルは上と同じ
cssファイルは上と同じ

index.js
function get_message() {
    var now_date = new Date();
    var month = now_date.getMonth() + 1;
    return now_date.getFullYear() + "" 
    + month + ""
    + now_date.getDate() + "" 
    + now_date.getHours() + ""
    + now_date.getMinutes() + ""
    + now_date.getSeconds() + "";
}
index.html
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='index.css') }}">
<script type=text/javascript src="{{ url_for('static', filename='index.js') }}"></script>

<body>
<h1 id="hello"> HELLOW FLASK </h1>
<p id="nowtime"> </p>
<script type="text/javascript">
    var nowtime_doc = document.getElementById("nowtime");
    nowtime_doc.innerHTML = "TIME " + get_message();
</script>
</body>

実行後、ブラウザでhttp://localhost:5000/index に接続するとHELLO FLASKの下に現在の日時が表示されるはずです。
これでWEBページにjavascriptが適用できました。

WEBページの共通部を別ファイルにする

WEBページでは、ヘッダやフッダなど複数のページで共通の箇所があることが多いです。
そのような場合、flaskではテンプレートエンジンの機能を使用してファイルを外だしして使用することができます。
共通ファイル(layout.html)には{% block time %}と{% endblock %}で個別ファイルの処理が入る場所を定義しています。
個別ファイル(index.html)には{% extends "layout.html" %}で引用する共通ファイルを定義して、{% block time %}から{% endblock %}の中に処理を書きます。

ディレクトリ構成

root\
  |--static\
  |   --index.css
  |   --index.js
  |--templates\
  |   --layout.html
  |   --index.html
  |--flask_main.py

pythonファイルは上と同じ
cssファイルは上と同じ
jsファイルは上と同じ

layout.html
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='index.css') }}">
<script type=text/javascript src="{{ url_for('static', filename='index.js') }}"></script>

<body>
    <h1 id="hello"> HELLOW FLASK </h1>
    {% block time %}{% endblock %}
</body>
index.html
{% extends "layout.html" %}
{% block time %}

<p id="nowtime"> </p>

<script type="text/javascript">
var nowtime_doc = document.getElementById("nowtime");
nowtime_doc.innerHTML = "TIME " + get_message();

</script>
{% endblock %}

実行後、ブラウザでhttp://localhost:5000/index に接続すると先ほどと同様にHELLO FLASKの下に現在の日時が表示されるはずです。
これでWEBページをlayout.htmlとindex.htmlに分けることができました。

パスを変更する。

今まで出てきたtemplatesやstaticはflaskがデフォルトで設定したパスなので、ディレクトリ構成が固定されていました。
でもよくよく考えるとpythonファイルとhtmlファイルとjavaScriptファイルが同じ階層なのが気に入りませんでした。
まずはユーザ側で動くファイル(htmlとjavaScript)とサーバ側で動くファイルを分けました。

ディレクトリ構成

root\
  |--html\
  |   |--static\
  |   |    |--css\
  |   |    |   |--index.css
  |   |    |--js\
  |   |    |   |--index.js
  |   |--templates\
  |   |    |--layout.html
  |   |    |--index.html
  |--flask_main.py
flask_main.py
from flask import Flask, render_template

app = Flask(__name__, static_folder='html/static', template_folder='html/templates')

@app.route('/index')
def index():
    return render_template('index.html')

if __name__ == "__main__":
    app.run()
layout.html
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/index.css') }}">
<script type=text/javascript src="{{ url_for('static', filename='js/index.js') }}"></script>

<body>
    <h1 id="hello"> HELLOW FLASK </h1>
    {% block content %}{% endblock %}
</body>

他は上と同じです。

次にpythonのurl部分と実処理部分を分けました。

root\
  |--html\
  |   |--static\
  |   |    |--css\
  |   |    |   |--index.css
  |   |    |--js\
  |   |    |   |--index.js
  |   |--templates\
  |   |    |--layout.html
  |   |    |--index.html
  |--pymod\
  |   |--endpoint
  |   |    |--index.py
  |--flask_main.py
flask_main.py
from flask import Flask, render_template
from pymod.endpoint.index import index_fnc

app = Flask(__name__, static_folder='html/static', template_folder='html/templates')

@app.route('/index')
def index():
    return index_fnc()

if __name__ == "__main__":
    app.run()
index.py
from flask import render_template

def index_fnc():
    return render_template('index.html')

おわりに

今回はflaskの使い方について細々と書いていきました。
書くにあたり数年前に初めてflaskに触ったときに躓いたことを見返しましたが、今となっては大抵理解や予想ができてしまう内容でした。
初めて触った時の疑問や躓きがわからないと他の人へ説明するときも苦労するため、初心を忘れないようにしないといけないかと思いつつ、忘れてしまったら説明が無理になるなと察しました。

mink0212
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした