Java には Spring のセットがありますが、少し面倒で、常に個人でプレイする必要はありません (使いこなせば、それでも効率は良いです) Python の Web フレームワークには、django や flask などが含まれます。
最初に環境をインストールする
pip install flask
最新バージョンをインストールできます
公式ウェブサイトのチュートリアルに従ってください
最小限のアプリケーション
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
- まず、
Flask
クラス。このクラスのインスタンスが WSGI アプリケーションになります。 - 次に、このクラスのインスタンスを作成します。最初のパラメータは、アプリケーション モジュールまたはパッケージの名前です。(この例のように) 単一のモジュールを使用している場合は、
__name__
モジュールがアプリケーションごとに使用されるか、モジュールとしてインポートされるか (「main」または実際のインポートの名前)に応じて名前が変わるため、 を使用する必要があります。 )。このパラメータは、Flask がテンプレートや静的ファイルなどの場所を認識するために必要です。詳細についてはFlask
、ドキュメントを。 - 次に、
route()
デコレーター、関数をトリガーする URL を Flask に伝えます。 - 関数名は、関連付けられた URL を生成するために使用されます。この関数は最終的に、ユーザーのブラウザに表示する必要がある情報を返します。
WSGI の概要:
正式名は Python Web サーバー ゲートウェイ インターフェイスで、一連の Web サーバー間での Web アプリケーションの移植性を向上させるために、Web サーバーと Python Web アプリケーションまたは Web フレームワーク間の標準インターフェイスを指定します。詳細については公式
上記の紹介から、次のことがわかります。
- WSGI は、インターフェイスの標準プロトコル/仕様のセットです。
- 通信 (ロール) セクションは、Web サーバーと Python Web アプリケーションの間で行われます。
- 目的は、さまざまな Web サーバーがさまざまな Python プログラムと通信できるようにするための標準を開発することです。
flask.py
Flask 自体と競合するため、アプリケーション名として使用しないでください。
flaskコマンドまたは Python-m
スイッチを使用してアプリケーションを実行します。アプリケーションを実行する前に、ターミナルでFLASK_APP
環境。
$ export FLASK_APP=hello.py
$ flask run
* Running on http://127.0.0.1:5000/
flask run -h [host] -p [port] でホストとポートを指定します。
export FLASK_ENV=development
開発環境の機能を開く
- デバッガを起動します。
- 自動リロードを有効にします。
- Flask アプリケーションのデバッグ モードをオンにします。
をエクスポートするFLASK_DEBUG=1
ことで。運用環境ではデバッガを使用しないでください。
ルーティング
最新の Web アプリケーションはすべて意味のある URL を使用しているため、ユーザーが覚えやすくなり、Web ページがユーザーに好まれるようになり、リターン率が向上します。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'index page'
# print(__name__)
@app.route('/hello')
def hello():
return 'hello world'
URL の一部を動的に変更でき、関数に複数のルールを指定できます。
@app.route('/user/<username>')
def show_user_profile(username):
# 显示用户名
return 'User {}'.format(username)
@app.route('/post/<int:post_id>')
def show_post(post_id):
# 显示提交整型的用户"id"的结果,注意"int"是将输入的字符串形式转换为整型数据
return 'Post {}'.format(post_id)
@app.route('/path/<path:subpath>')
def show_subpath(subpath):
# 显示 /path/ 之后的路径名
return 'Subpath {}'.format(subpath)
コンバータの主な種類は次のとおりです。
タイプ | 意味 |
---|---|
弦 | デフォルトのデータ型は、スラッシュ「/」のない文字列を受け入れます。 |
整数 | 整数を受け入れる |
浮く | 浮動小数点型を受け入れます |
道 | 文字列と似ていますが、スラッシュ「/」を受け入れます |
uuid | uuid文字列のみを受け入れます |
固有の URL/リダイレクト動作
次の 2 つのルールの違いは、末尾のスラッシュが使用されるかどうかです。:
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
projects
の URL は行儀よく、末尾にスラッシュがあり、フォルダーのように見えます。末尾にスラッシュのない URL にアクセスすると、Flask は末尾にスラッシュを追加するように自動的にリダイレクトします。
about
URL には末尾のスラッシュがないため、ファイルのように動作します。末尾にスラッシュを付けてこの URL にアクセスすると、404 エラーが発生します。これにより、URL が一意に保たれ、検索エンジンが同じページに 2 回インデックスを作成することを回避できます。
URLを構築する
url_for() 関数を使用する
url_for()
function は、指定された関数の URL を構築するために使用されます。最初の引数として関数名を受け取ります。キーワード引数はいくつでも受け入れることができ、それぞれが URL 内の変数に対応します。不明な変数はクエリ パラメーターとして URL に追加されます。
テンプレートに URL をハードコードせず、逆関数を使用してurl_for()
動的に。
- 通常、リバースはハードコードされた URL よりも説明的です。
- URL は、あちこち探し回らなくても 1 か所だけ変更できます。
- URL の作成では、特殊文字と Unicode データのエスケープが自動的に処理されます。これは直感的です。
- 本番環境のパスは常に絶対パスであるため、相対パスの副作用を回避できます。
- アプリケーションが URL ルート パスの外側に配置されている場合 (
/myapplication
たとえば、 ではなく/
内)、url_for()
アプリケーションは適切に処理されます。
HTTPメソッド
Web アプリケーションは、さまざまな HTTP メソッドを使用して URL を処理します。Flask を使用する場合は、HTTP メソッドに精通している必要があります。デフォルトでは、ルーターはGET
リクエストに。デコレーターの引数を使用して、さまざまな HTTP メソッドroute()
を処理できます。methods
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return do_the_login()
else:
return show_the_login_form()
GET メソッドが現在使用されている場合、Flask はHEAD
メソッドの、 HTTP RFCHEAD
に従ってリクエストも処理します。同様に、OPTIONS
これも自動的に行われます。
静的ファイル
動的 Web アプリケーションには静的ファイル (通常は CSS および JavaScript ファイル) も必要です。理想的には、サーバーは静的ファイルを提供するようにすでに構成されています。しかし、開発中は、Flask もうまく機能します。パッケージまたはモジュールの隣に urlstatic
という。静的ファイルはアプリの/static
に。
特定の'static'
エンドポイント対応する URL を生成する
url_for('static', filename='style.css')
ファイルシステム内のこの静的ファイルの場所は、 である必要がありますstatic/style.css
。
レンダリングテンプレート
Python 内で HTML を生成するのは面白くないし、むしろ不器用です。アプリケーションのセキュリティを確保するには、HTML エスケープを自分で処理する必要があるためです。したがって、Flask は自動的にJinja2テンプレート エンジンを設定します。
Flask はフォルダー内のテンプレートを検索templates
します。したがって、アプリケーションがモジュールの場合、このフォルダーはモジュールの隣にあり、パッケージの場合、このフォルダーはパッケージ内にあります。
<!DOCTYPE html>
<title>Hello From Flask</title>
{% if name %}
<!-- 如果 name 不为空则将 name 渲染出来 -->
<h1>Hello {
{ name }}!</h1>
{% else %}
<!-- 如果 name 为空则打印 Hello World! -->
<h1>Hello World!</h1>
{% endif %}
テンプレート内でrequest、session、gオブジェクトを使用したり、 get_flashed_messages()関数を使用したりすることもできます。
テンプレートの継承は非常に便利です。テンプレートの継承がどのように機能するかを知りたい場合は、ドキュメント「テンプレートの継承」を参照してください。基本的なテンプレートの継承により、特定の要素 (ヘッダー、ナビゲーション、フッターなど) を各ページに表示できるようになります。
CSSファイルをインポートする
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<link
rel="stylesheet"
type="text/css"
href="{
{ url_for('static', filename='style.css') }}"
/>
</head>
<body>
<h1>Hello ShiYanLou {
{name}}</h1>
</body>
</html>
リクエストデータの受信
Flask では、この情報はグローバル オブジェクトrequest
によって。Python の経験があれば、このオブジェクトがどのようにしてグローバルになり得るのか、また Flask がどのようにしてスレッドの安全性を保証できるのか疑問に思うでしょう。答えはコンテキストスコープです
リクエストオブジェクト
まず、flask モジュールからインポートする必要がありますrequest
。
from flask import request
現在のリクエストのメソッドには、method
プロパティを使用してアクセスできます。form
属性を使用してフォーム データにPOST
アクセスできます(データはPUT
または に渡されます)。
上記のキー値が属性に存在しない場合はform
どうなりますか? この場合、スペシャルがトリガーされますKeyError
。通常のキャプチャと同じようにキャプチャできますKeyError
が、キャプチャできない場合はHTTP 400 Bad Request
エラー ページが表示されます。したがって、多くの場合、これに対処する必要はありません。
args
属性を使用して、URL ( ?key=value )
次の場所で送信されたパラメータを受け取ることができます。
searchword = request.args.get('key', '')
ユーザーが URL を変更する可能性があり、ページを表示するのはユーザーフレンドリーではないため、 get
URL パラメーターまたはキャプチャを使用して URL にアクセスすることをお勧めします。KeyError
400 bad request
ファイルのアップロード
Flask を使用すると、ファイルのアップロードを簡単に処理できます。HTML フォームに属性を設定することを忘れないように注意してくださいenctype="multipart/form-data"
。設定しないと、ブラウザはファイルを配信できません。
アップロードされたファイルは、メモリまたはファイル システム上の一時的な場所に保存されます。これらのファイルには、リクエスト オブジェクトのプロパティを通じてアクセスできますfiles
。アップロードされた各ファイルは、この属性辞書に保存されます。これは標準の Pythonfile
オブジェクトのように動作しますが、save()
サーバーのファイル システムにファイルを保存できるメソッドも備えています。
アップロードされたファイルは、メモリまたはファイル システム上の一時的な場所に保存されます。アップロードされたファイルには、リクエスト オブジェクトのfiles
プロパティ。アップロードされた各ファイルは、この辞書タイプのプロパティに保存されます。この属性は基本的に標準の Python オブジェクトと同じですfile
が、アップロードされたファイルをサーバーのファイル システムに保存するための追加のsave()
メソッド。次の例は、その仕組みを示しています。
from flask import request
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/uploaded_file.txt')
アプリケーションにアップロードする前にクライアント側のファイルの名前を知りたい場合は、filename
プロパティにアクセスできます。ただし、この値は偽装される可能性があるため、決して信頼しないでください。クライアントのファイル名を使用してファイルをサーバーに保存する場合は、それをWerkzeug
提供されたsecure_filename()
関数に渡します。
from flask import request
from werkzeug import secure_filename
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/' + secure_filename(f.filename))
...
ファイルアップロードスキーム
import os
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = {
'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
まず、大量のものをインポートしましたが、そのほとんどは理解しやすいものです。werkzeug.secure_filename()
後で説明します。UPLOAD_FOLDER
これは、アップロードされたファイルを保存するディレクトリであり、ALLOWED_EXTENSIONS
アップロードが許可されているファイル拡張子のコレクションです。
次の関数は、拡張子が有効かどうかを確認し、ファイルをアップロードして、アップロードされたファイルの URL にユーザーをリダイレクトします。
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit an empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('uploaded_file',
filename=filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=Upload>
</form>
'''
それで、secure_filename()
その機能は?ルールの 1 つは、「ユーザー入力を決して信用しない」です。同じ原則が、アップロードされたファイルのファイル名にも当てはまります。送信されたフォーム データはすべて偽物である可能性があり、ファイル名は危険である可能性があります。この時点で覚えておいてください。ファイルシステムにファイルを保存する前に、必ずこの関数を使用してファイル名をサニタイズしてください。
クッキー
Cookie にアクセスするには、cookies
属性を。Cookie は、 Response オブジェクトのset_cookie
メソッド。リクエスト オブジェクトのcookies
プロパティはクライアントによって送信されたすべての Cookie を含む辞書です。Flask では、セッションを、セッションの方。
Cookie を読み取ります:
from flask import request
@app.route('/')
def index():
username = request.cookies.get('username')
# use cookies.get(key) instead of cookies[key] to not get a
# KeyError if the cookie is missing.
リダイレクト
redirect()
リダイレクトするには関数を使用します。abort()
エラー コードを表示してリクエストを早期に終了するには、次のように使用します。
from flask import abort, redirect, url_for
@app.route('/')
def index():
return redirect(url_for('login'))
@app.route('/login')
def login():
abort(401)
this_is_never_executed()
上記の例は実際には無意味で、ユーザーをインデックス ページからアクセスできないページ (401 は禁止を意味します) にリダイレクトします。ただし、上記の例は、リダイレクトとバウンスがどのように機能するかを示すことができます。
デフォルトでは、各エラー コードに白黒のエラー ページが表示されます。errorhandler()
エラー ページは、デコレータを使用してカスタマイズできます。
from flask import render_template
@app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html'), 404
render_template()
次のに注意してください404
。これは、ページのエラー コードが 404、つまりページが存在しないことを意味します。デフォルトでは、200 は、すべてが正常であることを意味します。
応答
ビュー関数の戻り値は、自動的に応答オブジェクトに変換されます。戻り値が文字列の場合、応答本文が文字列、エラー コードが200 OK
メディア タイプである応答オブジェクトに変換されますtext/html
。Flask が戻り値を応答オブジェクトに変換するロジックは次のとおりです。
- 有効な応答オブジェクトが返された場合、それはビューから直接返されます。
- 文字列が返された場合、文字列データとデフォルトのパラメータを使用して応答オブジェクトが作成されます。
- タプルが返され、タプル内の要素が追加情報を提供できる場合。このようなタプルは
response, status, headers
( ) の形式であり、少なくとも 1 つの要素が含まれている必要があります。status
この値はステータス コードをオーバーライドします。ステータス コードheaders
は、追加のヘッダー値のリストまたは辞書にすることができます。 - 上記の条件がいずれも満たされない場合、Flask は戻り値が有効な WSGI アプリケーションであると想定し、それをリクエスト オブジェクトに変換します。
会話
request オブジェクトに加えて、リクエスト間の情報を保存できる ansession
と呼ばれる。このオブジェクトは、キー署名で暗号化された Cookie と同等です。つまり、ユーザーは Cookie を表示できますが、キーがなければ変更できません。
セッションを使用する前に、キーを設定する必要があります。例えば:
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
# Set the secret key to some random bytes. Keep this really secret!
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
@app.route('/')
def index():
if 'username' in session:
return 'Logged in as %s' % escape(session['username'])
return 'You are not logged in'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return '''
<form method="post">
<p><input type=text name=username>
<p><input type=submit value=Login>
</form>
'''
@app.route('/logout')
def logout():
# remove the username from the session if it's there
session.pop('username', None)
return redirect(url_for('index'))
ここで使用されるescape()
はエスケープに使用されます。テンプレートエンジンを使用しない場合は、この関数を使用して上記の例のようにエスケープできます
メッセージの点滅
優れたアプリとユーザー インターフェイスはフィードバックがすべてです。ユーザーから十分なフィードバックが得られないと、アプリが嫌いになる可能性があります。Flask は、メッセージ フラッシュ システムを通じてユーザーにフィードバックを提供する非常に簡単な方法を提供します。メッセージ フラッシュ システムは基本的に、リクエストの最後に情報をログに記録し、次の (そしてその次の) リクエストでその情報にアクセスできるようにします。通常はテンプレート レイアウトと組み合わせてメッセージを表示します。
flash()
メソッドを使用してメッセージをフラッシュしたり、get_flashed_messages()
メッセージを取得したりできます。get_flashed_messages()
また、テンプレートでも使用できます。
ロギングと WSGI ミドルウェアとの統合
ログ
理論的には、扱っているデータは正しいはずですが、実際には正しくないという状況に遭遇することがあります。たとえば、クライアント コードがあり、そのコードは HTTP リクエストをサーバーに送信しますが、明らかに間違っています。これは、ユーザーによるデータの改ざん、またはクライアント コードの障害が原因である可能性があります。ほとんどの場合、この状況では戻る400 Bad Request
だけで問題ありませんが、場合によってはそれができず、コードが動作し続けなければならない場合があります。
また、発生した異常な出来事を記録したい場合もあります。ここでログが役に立ちます。Flask 0.3 のロギングは事前設定されているため
WSGIミドルウェアの統合
WSGI ミドルウェアをアプリケーションに追加する場合は、内部 WSGI アプリケーションをラップできます。たとえば、Werkzeug パッケージのミドルウェアの 1 つを使用して lighttpd のバグを回避したい場合は、次のようにすることができます。
from werkzeug.contrib.fixers import LighttpdCGIRootFix
app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)
練習
ホーム ページ ビュー、新規ブログ ビュー、ログイン ビューなどの初期イメージの 4 つのビュー機能と 3 つのテンプレート ファイルの準備が含まれます。最後に、ページを美しくする style.css ファイルを記述します。完了すると、プロジェクトを開始して、ログインやブログなどのアクションを実行できるようになります。