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)