Webフレームワーク。pip install flaskでインストール。
Flaskオブジェクトを作り(例:app)、@app.getデコレータでURLを指定する。その下の関数で文字列を返す。
実行はapp.run()。
from flask import Flask
app = Flask(__name__)
@app.get('/hello')
def hello():
return "Hello World!"
app.run()
これで http://localhost:5000/hello にアクセスすると Hello World! が表示される。
第一引数はホストIPアドレス指定。何も指定しないと127.0.0.1(=localhost)。しかし、この状態では外部から接続できない。外部接続可能にするにはIPアドレス0.0.0.0を指定する。
app.run("0.0.0.0")
ポート番号はデフォールトで5000。これを返るにはportを指定する。
app.run("0.0.0.0",port="8080") # ポート番号指定
デバッグモードはデフォールトでFalseなので、有効にするにはdebug=Trueを指定する。これを指定すると、エラー内容がブラウザに表示される。
app.run("0.0.0.0",debug=True)
templateフォルダを作成し、HTMLファイルを用意し、それを表示する。
テンプレート内に {{名前}}で変数を入れる場所を指定する。
<html>
<body>
<h1>Top</h1>
<p>{{mes}}</p>
</body>
</html>
python関数内では、render_template関数でテンプレートファイル名を指定する。
渡すデータを「名前=データ」で指定する。
from flask import Flask, render_template
app = Flask(__name__)
@app.get('/hello')
def hello():
return render_template("sample.html",mes="こんにちは")
app.run(debug=True)
リストを渡し、テンプレート側で全て表示する例
@app.get('/hello')
def hello():
names = ["山田","田中","佐藤"]
return render_template("sample.html",names=names)
テンプレート側では行頭に {% %} 内に通常のpythonスクリプトのように書ける。
ただし、forの最後には endfor 、ifの最後には、endifを書く。
{% for name in names %}
<p>{{ name }}</p>
{% endfor %}
現在のループ回数の取得は、loop.index で可能。これは1から数えるので、0からの場合には、loop.index0 とする。
<table>
{% for s in slist %}
<tr>
<td>{{s.sid}}</td>
<td>{{s.sname}}</td>
<td>{{s.tanka}}</td>
</tr>
{% endfor %}
</table>
{% if tanka>200 %}
高額
{% else %}
低額
{% endif %}
{% set num = 10 %}
{{num}}
全ファイル共通のテンプレートを作り、各ファイルで使うことが出来る。
<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
{% block content %}
<!-- ここに個別ファイルが入る -->
{% endblock %}
</body>
</html>
このファイルがtemplate.htmlの場合、これを使う個別ファイルは以下のように書く
{% extends "template.html" %}
{% block content %}
<h1>Top</h1>
<p>{{mes}}</p>
{% endblock %}
HTMLをそのまま出したい場合「 | safe」を付ける。ただし、クロスサイトスクリプティングの危険性に配慮すること。確実に安全なデータにしか使うことは出来ない。
{{ name | safe}}
css、JavaScript、画像などの静的ファイルは /static フォルダに置き、/static/ファイル名 でアクセスする。
/hello/abc などのabc部分を受け取る
@app.get('/hello/<name>')
def hello(name):
return render_template("sample.html",mes=name + "さんこんにちは")
app.run(debug=True)
/hello/10 など数値だけを受け取る
@app.get('/hello/<int:num>')
def hello(num):
return render_template("sample.html",mes="数値:" + str(num))
app.run(debug=True)
<p>{{num}}</p>
<form method="post">
<input type="text" name="num">
<input type="submit" value="送信">
</form>
POSTのデータ取得は request.form['名前']
@app.post('/hello')
def do_hello():
num = request.form['num']
return render_template("form.html",num=num)
GETのデータ取得は request.args['名前']
@app.get('/hello')
def hello():
num = request.args['num']
return template("form.html",num=num)
GETのデータ取得で未指定時のデフォールトを指定するには、request.args.get('名前', 'デフォールト値')
@app.get('/hello')
def hello():
# numの指定が無いときには100
num = request.args.get('num', 100)
return template("form.html",num=num)
同じ名前を指定した部品から複数の値をリストで受け取るには、getlistを使う。
@app.get('/hello')
def hello():
nums = request.form.getlist('nums')
return template("form.html",nums=nums)
リダイレクトは redirect をインポートして以下を行う。
# / アクセス時 helloにリダイレクト
@app.get('/')
def index():
return redirect('/hello')
セッションは まずsession をインポート
from flask import Flask, redirect, render_template, request, session
まず app.secret_key を設定する。
app.secret_key = b'\x83\xc9L:\xdf\x8a\x97\xb9\xef\xc4}G\t\xed\x1b('
キーはコマンドラインから以下のようにして生成する。
python -c "import os; print(os.urandom(16))"
セッションはsessionという名前の辞書として値を代入する。
session['name'] = name
ログインしているかの確認例
@app.get('/')
def index():
if 'name' in session:
name = session['name']
return render_template("hello.html",title="ログイン",name=name)
else:
return redirect('/login')
ログアウト
session.pop('name', None)
セッション使用時に、フラッシュメッセージを利用可能。一度のみ使えるメッセージでエラーメッセージなどに使用する。
Python内でメッセージを指定
flash("IDまたはパスワードが違います")
HTML内でメッセージを表示
{% for message in get_flashed_messages() %}
<p>{{ message }}</p>
{% endfor %}
flash("IDまたはパスワードが違います","error")
HTML内でカテゴリをタグのclassに指定。classごとに色分けする。
{% for category, message in get_flashed_messages(with_categories=true) %}
<p class="{{category}}">{{ message }}</p>
{% endfor %}
/fileupに作成
<form action="/up" method="post" enctype="multipart/form-data"> <input type="file" name="upfile"> <input type="submit" value="アップロード"> </form>
@app.post('/up')
def up():
if 'upfile' not in request.files:
flash("ファイルがありません", "error-info")
return redirect(f'/fileup')
file = request.files['upfile']
orgname = file.filename
if orgname=='':
flash("ファイルが選択されていません", "error-info")
return redirect(f'/fileup')
# c:\pythonに保存する場合
fname = 'c:\\python\\{orgname}'
file.save(fname)
return redirect(f'/fileup')
通常のFlaskは1ファイルに全てのURLに対応する関数を定義する。複数ファイルに分ける場合、パッケージに分けて対処する。
まず、フォルダの配下にwebなどのフォルダを作り、そこにFlask用のファイルを置く。データベース用モジュールは別途dbフォルダに置く
| フォルダ | ファイル名 | 内容 |
|---|---|---|
| 直下 | app.py | 実行ファイル |
| web | __init__.py | Flaskのappを生成するファイル。ファイル名は固定 |
| web | module1.py | 分割したファイルその1。 |
| web | module2.py | 分割したファイルその2。 |
| web/templates | XXX.htmlなど | テンプレートファイル。 |
| web/static | XXX.cssなど | 静的ファイル。 |
| db | shouhin.py | データベース用のモジュール。 |
このファイルを実行する。
from web import app app.run(debug=True)
webフォルダ配下に必ずこのファイル名で置く。これにより、webパッケージの初期化を行う。
from flask import Flask app = Flask(__name__) # モジュールを全てインポート import web.module1 import web.module2
appをインポートし、あとは通常と同じ
from flask import Flask, render_template, request, redirect
from web import app
@app.get('/')
def module1():
return render_template('module1.html')
データベースのモジュールが/dbに置かれているときの使用例。db.shouhinでインポート。
from flask import Flask, render_template, request, redirect
from web import app
import db.shouhin
@app.get('/shouhin')
def shouhin_find():
row = db.shouhin.find(1)
return render_template('shouhin.html', shouhin = row)