Python が Web フレームワーク Flask を使用してプロジェクトを開発する方法
1. はじめに
Flask は、Python ベースの軽量 Web フレームワークです。
このドキュメントのコードは Python 3 を使用して実行されます。
コマンド ライン操作を練習し、このチュートリアルのコードを Linux で実行することをお勧めします。
2. インストール
pip3 を介して Flask をインストールするだけです:
$ sudo pip3 install Flask
Python 対話モードに入り、Flask の概要とバージョンを確認します:
$ python3 >>> import flask >>> print(flask.__doc__) flask ~~~~~ A microframework based on Werkzeug. It's extensively documented and follows best practice patterns. :copyright: © 2010 by the Pallets team. :license: BSD, see LICENSE for more details. >>> print(flask.__version__) 1.0.2
3。 Hello World から始める
このセクションの主な内容: Flask を使用して「Hello World!」を表示する Web プログラムを作成し、Flask を構成およびデバッグする方法。
3.1 Hello World
次のコマンドに従って、Flask プロジェクト HelloWorld を作成します。
mkdir HelloWorld mkdir HelloWorld/static mkdir HelloWorld/templates touch HelloWorld/server.py
static
および templates
ディレクトリは次のとおりです。このうち、static
は、画像、js、css ファイルなどの静的リソースを保存するために使用されます。 templates
ストレージ テンプレート ファイル。
私たちの Web サイトのロジックは基本的にserver.py ファイル内にあります。もちろん、このファイルには他の名前を付けることもできます。
次のコンテンツをserver.pyに追加します:
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' if __name__ == '__main__': app.run()
server.pyを実行します:
$ python3 server.py * Running on http://127.0.0.1:5000/
ブラウザを開いてhttp://127.0.0.1:5000/にアクセスします。参照 Hello World!
がページに表示されます。
次の情報がターミナルに表示されます:
127.0.0.1 - - [16/May/2014 10:29:08] "GET / HTTP/1.1" 200 -
変数 app は、次のメソッドを使用した Flask インスタンスです:
@app.route('/') def hello_world(): return 'Hello World!'
クライアントが / にアクセスすると、 hello_world () 関数によって返されるコンテンツに応答します。これは Hello World! を返すほど単純ではないことに注意してください。Hello World! は HTTP 応答メッセージのエンティティ部分にすぎません。ステータス コードなどの情報は Flask によって自動的に処理されるか、プログラミングによって定式化されます。
3.2 Flask の構成を変更する
app = Flask(__name__)
上記のコードでは、Python 組み込み変数 __name__
の値は文字列 __main__ です。
。 Flask クラスは、このパラメータをプログラム名として受け取ります。もちろん、これは app = Flask("my-app")
のようにカスタマイズできます。
Flask は、デフォルトで静的リソースの保存に static
ディレクトリを使用し、テンプレートの保存に templates
ディレクトリを使用します。これはパラメータを設定することで変更できます:
app = Flask("my-app", static_folder="path2", template_folder="path3")
詳細 パラメータについては __doc__
を参照してください:
from flask import Flask print(Flask.__doc__)
3.3 デバッグ モード
上記の server.py は app.run()# で実行されます。 ## モード このモードでは、サーバー側でエラーが発生した場合、クライアント側ではエラーが表示されません。ただし、開発環境ではエラーメッセージを表示する必要があるため、エラーメッセージを表示するには、
app.run(debug=True)
debug to
True# のように Flask を実行する必要があります。 ## のもう 1 つの利点は、プログラムの開始後にソース コードが変更されたかどうかを自動的に検出し、変更があった場合はプログラムを自動的に再起動することです。これにより時間を大幅に節約できます。 3.4 IP とポートのバインド
デフォルトでは、Flask は IP を
127.0.0.1 にバインドし、ポートを 5000
にバインドします。次の方法でカスタマイズすることもできます。 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>app.run(host=&amp;#39;0.0.0.0&amp;#39;, port=80, debug=True)</pre><div class="contentsignin">ログイン後にコピー</div></div>
は、コンピュータのすべての IP を表します。 80
は、HTTP Web サイト サービスのデフォルト ポートです。デフォルトとは何ですか?たとえば、Web サイト http://www.example.com
にアクセスすると、実際には http://www.example.com:80
にアクセスしますが、: 80
は省略可能です。 ポート 80 がバインドされているため、server.py は root 権限で実行する必要があります。つまり:
$ sudo python3 server.py
4. URL パラメータの取得
URL パラメータは、http://127.0.0.1:5000/?disp=3 など、URL に表示されるキーと値のペアです。 URL パラメータは
{'disp':3} です。 4.1 Flask プロジェクトの作成
次のコマンドに従って Flask プロジェクト HelloWorld:
mkdir HelloWorld mkdir HelloWorld/static mkdir HelloWorld/templates touch HelloWorld/server.py
4.2 すべての URL パラメーターをリストします
サーバーに追加します。 py 次のコンテンツ:
from flask import Flask, request app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): return request.args.__str__() if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
ブラウザで http://127.0.0.1:5000/?user=Flask&time&p=7&p=8 にアクセスすると、表示されます:
ImmutableMultiDict([(&#39;user&#39;, &#39;Flask&#39;), (&#39;time&#39;, &#39;&#39;), (&#39;p&#39;, &#39;7&#39;), (&#39;p&#39;, &#39;8&#39;)])
新しいブラウザもサポートURL に中国語を直接入力し (最新の Firefox ブラウザを使用すると、中国語を URL 仕様に準拠したデータに変換できます)、ブラウザに http://127.0.0.1:5000/?info=This is love が表示されます。 :
ImmutableMultiDict([(&#39;info&#39;, &#39;这是爱,&#39;)])
ブラウザによって Flask サービスに送信されるデータはどのようなものですか?
request.full_path と request.path
を確認してください: <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class='brush:php;toolbar:false;'>from flask import Flask, request
app = Flask(__name__)
@app.route(&amp;#39;/&amp;#39;)
def hello_world():
print(request.path)
print(request.full_path)
return request.args.__str__()
if __name__ == &amp;#39;__main__&amp;#39;:
app.run(port=5000, debug=True)</pre><div class="contentsignin">ログイン後にコピー</div></div>
ブラウザ アクセス http://127.0.0.1:5000/?info=これは愛、server.py を実行しているターミナルは出力します:
##2./?info=This is love,
Forたとえば、キー
info
に対応する値を取得するには、server.py を次のように変更します:from flask import Flask, request app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): return request.args.get(&#39;info&#39;) if __name__ == &#39;__main__&#39;: app.run(port=5000)
server.py を実行し、ブラウザで http://127.0.0.1 にアクセスします: 5000 /?info=hello、ブラウザには次のように表示されます:
hello
info
が URL パラメーターに見つからなかったためです。したがって、request.args.get('info') は Python の組み込みの None を返しますが、Flask は None を返すことはできません。
解決策は非常に簡単です。最初に None かどうかを判断しましょう:
from flask import Flask, request app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): r = request.args.get(&#39;info&#39;) if r==None: # do something return &#39;&#39; return r if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
from flask import Flask, request app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): r = request.args.get(&#39;info&#39;, &#39;hi&#39;) return r if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
function
request.args.getの 2 番目のパラメーターは、デフォルト値を設定するために使用されます。この時、ブラウザで http://127.0.0.1:5000/ にアクセスすると、
と表示されます。hi
4.4 如何处理多值
还记得上面有一次请求是这样的吗? http://127.0.0.1:5000/?user=Flask&time&p=7&p=8,仔细看下,p
有两个值。
如果我们的代码是:
from flask import Flask, request app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): r = request.args.get(&#39;p&#39;) return r if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
在浏览器中请求时,我们只会看到7
。如果我们需要把p
的所有值都获取到,该怎么办?
不用get
,用getlist
:
from flask import Flask, request app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): r = request.args.getlist(&#39;p&#39;) # 返回一个list return str(r) if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
浏览器输入 http://127.0.0.1:5000/?user=Flask&time&p=7&p=8,我们会看到[&#39;7&#39;, &#39;8&#39;]
。
五、获取POST方法传送的数据
作为一种HTTP请求方法,POST用于向指定的资源提交要被处理的数据。我们在某网站注册用户、写文章等时候,需要将数据传递到网站服务器中。并不适合将数据放到URL参数中,密码放到URL参数中容易被看到,文章数据又太多,浏览器不一定支持太长长度的URL。这时,一般使用POST方法。
本文使用python的requests库模拟浏览器。
安装方法:
$ sudo pip3 install requests
5.1 建立Flask项目
按照以下命令建立Flask项目HelloWorld:
mkdir HelloWorld mkdir HelloWorld/static mkdir HelloWorld/templates touch HelloWorld/server.py
5.2 查看POST数据内容
以用户注册为例子,我们需要向服务器/register
传送用户名name
和密码password
。如下编写HelloWorld/server.py。
from flask import Flask, request app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): return &#39;hello world&#39; @app.route(&#39;/register&#39;, methods=[&#39;POST&#39;]) def register(): print(request.headers) print(request.stream.read()) return &#39;welcome&#39; if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
`@app.route(‘/register’, methods=[‘POST’])是指url
/register只接受POST方法。可以根据需要修改
methods`参数,例如如果想要让它同时支持GET和POST,这样写:
@app.route(&#39;/register&#39;, methods=[&#39;GET&#39;, &#39;POST&#39;])
浏览器模拟工具client.py内容如下:
import requests user_info = {&#39;name&#39;: &#39;letian&#39;, &#39;password&#39;: &#39;123&#39;} r = requests.post("http://127.0.0.1:5000/register", data=user_info) print(r.text)
运行HelloWorld/server.py,然后运行client.py。client.py将输出:
welcome
而HelloWorld/server.py在终端中输出以下调试信息(通过print
输出):
Host: 127.0.0.1:5000 User-Agent: python-requests/2.19.1 Accept-Encoding: gzip, deflate Accept: */* Connection: keep-alive Content-Length: 24 Content-Type: application/x-www-form-urlencoded b&#39;name=letian&password=123&#39;
前6行是client.py生成的HTTP请求头,由print(request.headers)
输出。
请求体的数据,我们通过print(request.stream.read())
输出,结果是:
b&#39;name=letian&password=123&#39;
5.3 解析POST数据
上面,我们看到post的数据内容是:
b&#39;name=letian&password=123&#39;
我们要想办法把我们要的name、password提取出来,怎么做呢?自己写?不用,Flask已经内置了解析器request.form
。
我们将服务代码改成:
from flask import Flask, request app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): return &#39;hello world&#39; @app.route(&#39;/register&#39;, methods=[&#39;POST&#39;]) def register(): print(request.headers) # print(request.stream.read()) # 不要用,否则下面的form取不到数据 print(request.form) print(request.form[&#39;name&#39;]) print(request.form.get(&#39;name&#39;)) print(request.form.getlist(&#39;name&#39;)) print(request.form.get(&#39;nickname&#39;, default=&#39;little apple&#39;)) return &#39;welcome&#39; if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
执行client.py请求数据,服务器代码会在终端输出:
Host: 127.0.0.1:5000 User-Agent: python-requests/2.19.1 Accept-Encoding: gzip, deflate Accept: */* Connection: keep-alive Content-Length: 24 Content-Type: application/x-www-form-urlencoded ImmutableMultiDict([(&#39;name&#39;, &#39;letian&#39;), (&#39;password&#39;, &#39;123&#39;)]) letian letian [&#39;letian&#39;] little apple
request.form
会自动解析数据。
request.form[&#39;name&#39;]
和request.form.get(&#39;name&#39;)
都可以获取name
对应的值。对于request.form.get()
可以为参数default
指定值以作为默认值。所以:
print(request.form.get(&#39;nickname&#39;, default=&#39;little apple&#39;))
输出的是默认值
little apple
如果name
有多个值,可以使用request.form.getlist(&#39;name&#39;)
,该方法将返回一个列表。我们将client.py改一下:
import requests user_info = {&#39;name&#39;: [&#39;letian&#39;, &#39;letian2&#39;], &#39;password&#39;: &#39;123&#39;} r = requests.post("http://127.0.0.1:5000/register", data=user_info) print(r.text)
此时运行client.py,print(request.form.getlist(&#39;name&#39;))
将输出:
[u&#39;letian&#39;, u&#39;letian2&#39;]
六、处理和响应JSON数据
使用 HTTP POST 方法传到网站服务器的数据格式可以有很多种,比如「5. 获取POST方法传送的数据」讲到的name=letian&password=123这种用过&
符号分割的key-value键值对格式。我们也可以用JSON格式、XML格式。相比XML的重量、规范繁琐,JSON显得非常小巧和易用。
6.1 建立Flask项目
按照以下命令建立Flask项目HelloWorld:
mkdir HelloWorld mkdir HelloWorld/static mkdir HelloWorld/templates touch HelloWorld/server.py
6.2 处理JSON格式的请求数据
如果POST的数据是JSON格式,request.json会自动将json数据转换成Python类型(字典或者列表)。
编写server.py:
from flask import Flask, request app = Flask("my-app") @app.route(&#39;/&#39;) def hello_world(): return &#39;Hello World!&#39; @app.route('/add', methods=['POST']) def add(): print(request.headers) print(type(request.json)) print(request.json) result = request.json['a'] + request.json['b'] return str(result) if __name__ == '__main__': app.run(host='127.0.0.1', port=5000, debug=True)
编写client.py模拟浏览器请求:
import requests json_data = {&#39;a&#39;: 1, &#39;b&#39;: 2} r = requests.post("http://127.0.0.1:5000/add", json=json_data) print(r.text)
运行server.py,然后运行client.py,client.py 会在终端输出:
3
server.py 会在终端输出:
Host: 127.0.0.1:5000 User-Agent: python-requests/2.19.1 Accept-Encoding: gzip, deflate Accept: */* Connection: keep-alive Content-Length: 16 Content-Type: application/json {&#39;a&#39;: 1, &#39;b&#39;: 2}
注意,请求头中Content-Type
的值是application/json
。
6.3 响应JSON-方案1
响应JSON时,除了要把响应体改成JSON格式,响应头的Content-Type
也要设置为application/json
。
编写server2.py:
from flask import Flask, request, Response import json app = Flask("my-app") @app.route(&#39;/&#39;) def hello_world(): return &#39;Hello World!&#39; @app.route('/add', methods=['POST']) def add(): result = {'sum': request.json['a'] + request.json['b']} return Response(json.dumps(result), mimetype='application/json') if __name__ == '__main__': app.run(host='127.0.0.1', port=5000, debug=True)
修改后运行。
编写client2.py:
import requests json_data = {&#39;a&#39;: 1, &#39;b&#39;: 2} r = requests.post("http://127.0.0.1:5000/add", json=json_data) print(r.headers) print(r.text)
运行client.py,将显示:
{&#39;Content-Type&#39;: &#39;application/json&#39;, &#39;Content-Length&#39;: &#39;10&#39;, &#39;Server&#39;: &#39;Werkzeug/0.14.1 Python/3.6.4&#39;, &#39;Date&#39;: &#39;Sat, 07 Jul 2018 05:23:00 GMT&#39;} {"sum": 3}
上面第一段内容是服务器的响应头,第二段内容是响应体,也就是服务器返回的JSON格式数据。
另外,如果需要服务器的HTTP响应头具有更好的可定制性,比如自定义Server
,可以如下修改add()
函数:
@app.route(&#39;/add&#39;, methods=[&#39;POST&#39;]) def add(): result = {&#39;sum&#39;: request.json[&#39;a&#39;] + request.json[&#39;b&#39;]} resp = Response(json.dumps(result), mimetype=&#39;application/json&#39;) resp.headers.add(&#39;Server&#39;, &#39;python flask&#39;) return resp
client2.py运行后会输出:
{&#39;Content-Type&#39;: &#39;application/json&#39;, &#39;Content-Length&#39;: &#39;10&#39;, &#39;Server&#39;: &#39;python flask&#39;, &#39;Date&#39;: &#39;Sat, 07 Jul 2018 05:26:40 GMT&#39;} {"sum": 3}
6.4 响应JSON-方案2
使用 jsonify 工具函数即可。
from flask import Flask, request, jsonify app = Flask("my-app") @app.route(&#39;/&#39;) def hello_world(): return &#39;Hello World!&#39; @app.route('/add', methods=['POST']) def add(): result = {'sum': request.json['a'] + request.json['b']} return jsonify(result) if __name__ == '__main__': app.run(host='127.0.0.1', port=5000, debug=True)
七、上传文件
上传文件,一般也是用POST方法。
7.1 建立Flask项目
按照以下命令建立Flask项目HelloWorld:
mkdir HelloWorld mkdir HelloWorld/static mkdir HelloWorld/templates touch HelloWorld/server.py
7.2 上传文件
这一部分的代码参考自How to upload a file to the server in Flask。
我们以上传图片为例:
假设将上传的图片只允许’png’、’jpg’、’jpeg’、’gif’这四种格式,通过url/upload
使用POST上传,上传的图片存放在服务器端的static/uploads
目录下。
首先在项目HelloWorld
中创建目录static/uploads
:
mkdir HelloWorld/static/uploads
werkzeug
库可以判断文件名是否安全,例如防止文件名是../../../a.png
,安装这个库:
$ sudo pip3 install werkzeug
server.py代码:
from flask import Flask, request from werkzeug.utils import secure_filename import os app = Flask(__name__) # 文件上传目录 app.config[&#39;UPLOAD_FOLDER&#39;] = &#39;static/uploads/&#39; # 支持的文件格式 app.config[&#39;ALLOWED_EXTENSIONS&#39;] = {&#39;png&#39;, &#39;jpg&#39;, &#39;jpeg&#39;, &#39;gif&#39;} # 集合类型 # 判断文件名是否是我们支持的格式 def allowed_file(filename): return &#39;.&#39; in filename and \ filename.rsplit(&#39;.&#39;, 1)[1] in app.config[&#39;ALLOWED_EXTENSIONS&#39;] @app.route(&#39;/&#39;) def hello_world(): return &#39;hello world&#39; @app.route(&#39;/upload&#39;, methods=[&#39;POST&#39;]) def upload(): upload_file = request.files[&#39;image&#39;] if upload_file and allowed_file(upload_file.filename): filename = secure_filename(upload_file.filename) # 将文件保存到 static/uploads 目录,文件名同上传时使用的文件名 upload_file.save(os.path.join(app.root_path, app.config[&#39;UPLOAD_FOLDER&#39;], filename)) return &#39;info is &#39;+request.form.get(&#39;info&#39;, &#39;&#39;)+&#39;. success&#39; else: return &#39;failed&#39; if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
app.config
中的config是字典的子类,可以用来设置自有的配置信息,也可以设置自己的配置信息。函数allowed_file(filename)
用来判断filename
是否有后缀以及后缀是否在app.config['ALLOWED_EXTENSIONS']
中。
客户端上传的图片必须以image01
标识。upload_file
是上传文件对应的对象。app.root_path
获取server.py所在目录在文件系统中的绝对路径。upload_file.save(path)
用来将upload_file
保存在服务器的文件系统中,参数最好是绝对路径,否则会报错(网上很多代码都是使用相对路径,但是笔者在使用相对路径时总是报错,说找不到路径)。函数os.path.join()
用来将使用合适的路径分隔符将路径组合起来。
好了,定制客户端client.py:
import requests file_data = {&#39;image&#39;: open(&#39;Lenna.jpg&#39;, &#39;rb&#39;)} user_info = {&#39;info&#39;: &#39;Lenna&#39;} r = requests.post("http://127.0.0.1:5000/upload", data=user_info, files=file_data) print(r.text)
运行client.py,当前目录下的Lenna.jpg将上传到服务器。
然后,我们可以在static/uploads中看到文件Lenna.jpg。
要控制上产文件的大小,可以设置请求实体的大小,例如:
app.config[&#39;MAX_CONTENT_LENGTH&#39;] = 16 * 1024 * 1024 #16MB
不过,在处理上传文件时候,需要使用try:...except:...
。
如果要获取上传文件的内容可以:
file_content = request.files[&#39;image&#39;].stream.read()
八、Restful URL
简单来说,Restful URL可以看做是对 URL 参数的替代。
8.1 建立Flask项目
按照以下命令建立Flask项目HelloWorld:
mkdir HelloWorld mkdir HelloWorld/static mkdir HelloWorld/templates touch HelloWorld/server.py
8.2 编写代码
编辑server.py:
from flask import Flask app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): return &#39;hello world&#39; @app.route(&#39;/user/&#39;) def user(username): print(username) print(type(username)) return &#39;hello &#39; + username @app.route(&#39;/user//friends&#39;) def user_friends(username): print(username) print(type(username)) return &#39;hello &#39; + username if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
运行HelloWorld/server.py。使用浏览器访问http://127.0.0.1:5000/user/letian,HelloWorld/server.py将输出:
letian
而访问http://127.0.0.1:5000/user/letian/,响应为404 Not Found。
浏览器访问http://127.0.0.1:5000/user/letian/friends,可以看到:
Hello letian. They are your friends.
HelloWorld/server.py输出:
letian
8.3 转换类型
由上面的示例可以看出,使用 Restful URL 得到的变量默认为str对象。如果我们需要通过分页显示查询结果,那么需要在url中有数字来指定页数。按照上面方法,可以在获取str类型页数变量后,将其转换为int类型。不过,还有更方便的方法,就是用flask内置的转换机制,即在route中指定该如何转换。
新的服务器代码:
from flask import Flask app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): return &#39;hello world&#39; @app.route(&#39;/page/&#39;) def page(num): print(num) print(type(num)) return &#39;hello world&#39; if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
`@app.route(‘/page/int:num‘)`会将num变量自动转换成int类型。
运行上面的程序,在浏览器中访问http://127.0.0.1:5000/page/1,HelloWorld/server.py将输出如下内容:
1
如果访问的是http://127.0.0.1:5000/page/asd,我们会得到404响应。
在官方资料中,说是有3个默认的转换器:
int accepts integers float like int but for floating point values path like the default but also accepts slashes
看起来够用了。
8.4 一个有趣的用法
如下编写服务器代码:
from flask import Flask app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): return &#39;hello world&#39; @app.route(&#39;/page/-&#39;) def page(num1, num2): print(num1) print(num2) return &#39;hello world&#39; if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
在浏览器中访问http://127.0.0.1:5000/page/11-22,HelloWorld/server.py会输出:
11 22
8.5 编写转换器
自定义的转换器是一个继承werkzeug.routing.BaseConverter
的类,修改to_python
和to_url
方法即可。to_python
方法用于将url中的变量转换后供被`@app.route包装的函数使用,to_url方法用于flask.url_for`中的参数转换。
下面是一个示例,将HelloWorld/server.py修改如下:
from flask import Flask, url_for from werkzeug.routing import BaseConverter class MyIntConverter(BaseConverter): def __init__(self, url_map): super(MyIntConverter, self).__init__(url_map) def to_python(self, value): return int(value) def to_url(self, value): return value * 2 app = Flask(__name__) app.url_map.converters[&#39;my_int&#39;] = MyIntConverter @app.route(&#39;/&#39;) def hello_world(): return &#39;hello world&#39; @app.route(&#39;/page/&#39;) def page(num): print(num) print(url_for(&#39;page&#39;, num=123)) # page 对应的是 page函数 ,num 对应对应`/page/`中的num,必须是str return &#39;hello world&#39; if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
浏览器访问http://127.0.0.1:5000/page/123后,HelloWorld/server.py的输出信息是:
123 /page/123123
九、使用url_for生成链接
工具函数url_for
可以让你以软编码的形式生成url,提供开发效率。
9.1 建立Flask项目
按照以下命令建立Flask项目HelloWorld:
mkdir HelloWorld mkdir HelloWorld/static mkdir HelloWorld/templates touch HelloWorld/server.py
9.2 编写代码
编辑HelloWorld/server.py:
from flask import Flask, url_for app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): pass @app.route(&#39;/user/&#39;) def user(name): pass @app.route(&#39;/page/&#39;) def page(num): pass @app.route(&#39;/test&#39;) def test(): print(url_for(&#39;hello_world&#39;)) print(url_for(&#39;user&#39;, name=&#39;letian&#39;)) print(url_for(&#39;page&#39;, num=1, q=&#39;hadoop mapreduce 10%3&#39;)) print(url_for(&#39;static&#39;, filename=&#39;uploads/01.jpg&#39;)) return &#39;Hello&#39; if __name__ == &#39;__main__&#39;: app.run(debug=True)
运行HelloWorld/server.py。然后在浏览器中访问http://127.0.0.1:5000/test,HelloWorld/server.py将输出以下信息:
/ /user/letian /page/1?q=hadoop+mapreduce+10%253 /static/uploads/01.jpg
十、使用redirect重定向网址
redirect
函数用于重定向,实现机制很简单,就是向客户端(浏览器)发送一个重定向的HTTP报文,浏览器会去访问报文中指定的url。
10.1 建立Flask项目
按照以下命令建立Flask项目HelloWorld:
mkdir HelloWorld mkdir HelloWorld/static mkdir HelloWorld/templates touch HelloWorld/server.py
10.2 编写代码
使用redirect
时,给它一个字符串类型的参数就行了。
编辑HelloWorld/server.py:
from flask import Flask, url_for, redirect app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): return &#39;hello world&#39; @app.route(&#39;/test1&#39;) def test1(): print(&#39;this is test1&#39;) return redirect(url_for(&#39;test2&#39;)) @app.route(&#39;/test2&#39;) def test2(): print(&#39;this is test2&#39;) return &#39;this is test2&#39; if __name__ == &#39;__main__&#39;: app.run(debug=True)
运行HelloWorld/server.py,在浏览器中访问http://127.0.0.1:5000/test1,浏览器的url会变成http://127.0.0.1:5000/test2,并显示:
this is test2
十一、使用Jinja2模板引擎
模板引擎负责MVC中的V(view,视图)这一部分。Flask默认使用Jinja2模板引擎。
Flask与模板相关的函数有:
flask.render_template(template_name_or_list, **context)
Renders a template from the template folder with the given context.flask.render_template_string(source, **context)
Renders a template from the given template source string with the given context.flask.get_template_attribute(template_name, attribute)
Loads a macro (or variable) a template exports. This can be used to invoke a macro from within Python code.
这其中常用的就是前两个函数。
这个实例中使用了模板继承、if判断、for循环。
11.1 建立Flask项目
按照以下命令建立Flask项目HelloWorld:
mkdir HelloWorld mkdir HelloWorld/static mkdir HelloWorld/templates touch HelloWorld/server.py
11.2 创建并编辑HelloWorld/templates/default.html
内容如下:
<html> <head> <title> {% if page_title %} {{ page_title }} {% endif %} </title> </head> <body> {% block body %}{% endblock %} ``` 可以看到,在``标签中使用了if判断,如果给模板传递了`page_title`变量,显示之,否则,不显示。 ``标签中定义了一个名为`body`的block,用来被其他模板文件继承。 ### 11.3 创建并编辑HelloWorld/templates/user_info.html 内容如下: ``` {% extends "default.html" %} {% block body %} {% for key in user_info %} {{ key }}: {{ user_info[key] }} {% endfor %} {% endblock %}
变量user_info
应该是一个字典,for循环用来循环输出键值对。
11.4 编辑HelloWorld/server.py
内容如下:
from flask import Flask, render_template app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): return &#39;hello world&#39; @app.route(&#39;/user&#39;) def user(): user_info = { &#39;name&#39;: &#39;letian&#39;, &#39;email&#39;: &#39;123@aa.com&#39;, &#39;age&#39;:0, &#39;github&#39;: &#39;https://github.com/letiantian&#39; } return render_template(&#39;user_info.html&#39;, page_title=&#39;letian\&#39;s info&#39;, user_info=user_info) if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
render_template()
函数的第一个参数指定模板文件,后面的参数是要传递的数据。
11.5 运行与测试
运行HelloWorld/server.py:
$ python3 HelloWorld/server.py
在浏览器中访问http://127.0.0.1:5000/user
查看网页源码:
<html> <head> <title> letian&&9;s info </title> </head> <body> name: letian <br/> email: 123@aa.com <br/> age: 0 <br/> github: https://github.com/letiantian <br/> </body> </html>
十二、自定义404等错误的响应
要处理HTTP错误,可以使用flask.abort
函数。
12.1 示例1:简单入门
建立Flask项目
按照以下命令建立Flask项目HelloWorld:
mkdir HelloWorld mkdir HelloWorld/static mkdir HelloWorld/templates touch HelloWorld/server.py
代码
编辑HelloWorld/server.py:
from flask import Flask, render_template_string, abort app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): return &#39;hello world&#39; @app.route(&#39;/user&#39;) def user(): abort(401) # Unauthorized 未授权 print(&#39;Unauthorized, 请先登录&#39;) if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
效果
运行HelloWorld/server.py,浏览器访问http://127.0.0.1:5000/user
要注意的是,HelloWorld/server.py中abort(401)后的print并没有执行。
12.2 示例2:自定义错误页面
代码
将服务器代码改为:
from flask import Flask, render_template_string, abort app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): return &#39;hello world&#39; @app.route(&#39;/user&#39;) def user(): abort(401) # Unauthorized @app.errorhandler(401) def page_unauthorized(error): return render_template_string(&#39; Unauthorized {{ error_info }}&#39;, error_info=error), 401 if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
page_unauthorized
函数返回的是一个元组,401 代表HTTP 响应状态码。如果省略401,则响应状态码会变成默认的 200。
效果
运行HelloWorld/server.py,浏览器访问http://127.0.0.1:5000/user
十三、用户会话
session用来记录用户的登录状态,一般基于cookie实现。
下面是一个简单的示例。
13.1 建立Flask项目
按照以下命令建立Flask项目HelloWorld:
mkdir HelloWorld mkdir HelloWorld/static mkdir HelloWorld/templates touch HelloWorld/server.py
13.2 编辑HelloWorld/server.py
内容如下:
from flask import Flask, render_template_string, \ session, request, redirect, url_for app = Flask(__name__) app.secret_key = &#39;F12Zr47j\3yX R~X@H!jLwf/T&#39; @app.route(&#39;/&#39;) def hello_world(): return &#39;hello world&#39; @app.route(&#39;/login&#39;) def login(): return render_template_string(page) @app.route(&#39;/do_login&#39;, methods=[&#39;POST&#39;]) def do_login(): name = request.form.get(&#39;user_name&#39;) session[&#39;user_name&#39;] = name return &#39;success&#39; @app.route(&#39;/show&#39;) def show(): return session[&#39;user_name&#39;] @app.route(&#39;/logout&#39;) def logout(): session.pop(&#39;user_name&#39;, None) return redirect(url_for(&#39;login&#39;)) if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
13.3 代码的含义
app.secret_key
用于给session加密。
在/login
中将向用户展示一个表单,要求输入一个名字,submit后将数据以post的方式传递给/do_login
,/do_login
将名字存放在session中。
如果用户成功登录,访问/show
时会显示用户的名字。此时,打开firebug等调试工具,选择session面板,会看到有一个cookie的名称为session
。
/logout
用于登出,通过将session
中的user_name
字段pop即可。Flask中的session基于字典类型实现,调用pop方法时会返回pop的键对应的值;如果要pop的键并不存在,那么返回值是pop()
的第二个参数。
另外,使用redirect()
重定向时,一定要在前面加上return
。
13.4 效果
进入http://127.0.0.1:5000/login,输入name,点击submit
进入http://127.0.0.1:5000/show查看session中存储的name:
13.5 设置sessin的有效时间
下面这段代码来自Is there an easy way to make sessions timeout in flask?:
from datetime import timedelta from flask import session, app session.permanent = True app.permanent_session_lifetime = timedelta(minutes=5)
这段代码将session的有效时间设置为5分钟。
十四、使用Cookie
Cookie是存储在客户端的记录访问者状态的数据。 常用的用于记录用户登录状态的session大多是基于cookie实现的。
cookie可以借助flask.Response
来实现。下面是一个示例。
14.1 建立Flask项目
按照以下命令建立Flask项目HelloWorld:
mkdir HelloWorld mkdir HelloWorld/static mkdir HelloWorld/templates touch HelloWorld/server.py
14.2 代码
修改HelloWorld/server.py:
from flask import Flask, request, Response, make_response import time app = Flask(__name__) @app.route(&#39;/&#39;) def hello_world(): return &#39;hello world&#39; @app.route(&#39;/add&#39;) def login(): res = Response(&#39;add cookies&#39;) res.set_cookie(key=&#39;name&#39;, value=&#39;letian&#39;, expires=time.time()+6*60) return res @app.route(&#39;/show&#39;) def show(): return request.cookies.__str__() @app.route(&#39;/del&#39;) def del_cookie(): res = Response(&#39;delete cookies&#39;) res.set_cookie(&#39;name&#39;, &#39;&#39;, expires=0) return res if __name__ == &#39;__main__&#39;: app.run(port=5000, debug=True)
由上可以看到,可以使用Response.set_cookie
添加和删除cookie。expires
参数用来设置cookie有效时间,它的值可以是datetime
对象或者unix时间戳,笔者使用的是unix时间戳。
res.set_cookie(key=&#39;name&#39;, value=&#39;letian&#39;, expires=time.time()+6*60)
上面的expire参数的值表示cookie在从现在开始的6分钟内都是有效的。
要删除cookie,将expire参数的值设为0即可:
res.set_cookie(&#39;name&#39;, &#39;&#39;, expires=0)
set_cookie()
函数的原型如下:
set_cookie(key, value=’’, max_age=None, expires=None, path=’/‘, domain=None, secure=None, httponly=False)
Sets a cookie. The parameters are the same as in the cookie Morsel object in the Python standard library but it accepts unicode data, too.
Parameters:
key – the key (name) of the cookie to be set.
value – the value of the cookie.
max_age – should be a number of seconds, or None (default) if the cookie should last only as long as the client’s browser session.
expires – should be a datetime object or UNIX timestamp.
domain – if you want to set a cross-domain cookie. For example, domain=”.example.com” will set a cookie that is readable by the domain www.example.com, foo.example.com etc. Otherwise, a cookie will only be readable by the domain that set it.
path – limits the cookie to a given path, per default it will span the whole domain.
14.3 运行与测试
运行HelloWorld/server.py:
$ python3 HelloWorld/server.py
使用浏览器打开http://127.0.0.1:5000/add,浏览器界面会显示
add cookies
下面查看一下cookie,如果使用firefox浏览器,可以用firebug插件查看。打开firebug,选择Cookies
选项,刷新页面,可以看到名为name
的cookie,其值为letian
。
在“网络”选项中,可以查看响应头中类似下面内容的设置cookie的HTTP「指令」:
Set-Cookie: name=letian; Expires=Sun, 29-Jun-2014 05:16:27 GMT; Path=/
在cookie有效期间,使用浏览器访问http://127.0.0.1:5000/show,可以看到:
{&#39;name&#39;: &#39;letian&#39;}
十五、闪存系统 flashing system
Flask的闪存系统(flashing system)用于向用户提供反馈信息,这些反馈信息一般是对用户上一次操作的反馈。反馈信息是存储在服务器端的,当服务器向客户端返回反馈信息后,这些反馈信息会被服务器端删除。
下面是一个示例。
15.1 建立Flask项目
按照以下命令建立Flask项目HelloWorld:
mkdir HelloWorld mkdir HelloWorld/static mkdir HelloWorld/templates touch HelloWorld/server.py
15.2 编写HelloWorld/server.py
内容如下:
from flask import Flask, flash, get_flashed_messages import time app = Flask(__name__) app.secret_key = &#39;some_secret&#39; @app.route(&#39;/&#39;) def index(): return &#39;hi&#39; @app.route(&#39;/gen&#39;) def gen(): info = &#39;access at &#39;+ time.time().__str__() flash(info) return info @app.route(&#39;/show1&#39;) def show1(): return get_flashed_messages().__str__() @app.route(&#39;/show2&#39;) def show2(): return get_flashed_messages().__str__() if __name__ == "__main__": app.run(port=5000, debug=True)
15.3 效果
运行服务器:
$ python3 HelloWorld/server.py
打开浏览器,访问http://127.0.0.1:5000/gen,浏览器界面显示(注意,时间戳是动态生成的,每次都会不一样,除非并行访问):
access at 1404020982.83
查看浏览器的cookie,可以看到session
,其对应的内容是:
.eJyrVopPy0kszkgtVrKKrlZSKIFQSUpWSknhYVXJRm55UYG2tkq1OlDRyHC_rKgIvypPdzcDTxdXA1-XwHLfLEdTfxfPUn8XX6DKWCAEAJKBGq8.BpE6dg.F1VURZa7VqU9bvbC4XIBO9-3Y4Y
再一次访问http://127.0.0.1:5000/gen,浏览器界面显示:
access at 1404021130.32
cookie中session
发生了变化,新的内容是:
.eJyrVopPy0kszkgtVrKKrlZSKIFQSUpWSknhYVXJRm55UYG2tkq1OlDRyHC_rKgIvypPdzcDTxdXA1-XwHLfLEdTfxfPUn8XX6DKWLBaMg1yrfCtciz1rfIEGxRbCwAhGjC5.BpE7Cg.Cb_B_k2otqczhknGnpNjQ5u4dqw
然后使用浏览器访问http://127.0.0.1:5000/show1,浏览器界面显示:
[&#39;access at 1404020982.83&#39;, &#39;access at 1404021130.32&#39;]
这个列表中的内容也就是上面的两次访问http://127.0.0.1:5000/gen得到的内容。此时,cookie中已经没有session
了。
如果使用浏览器访问http://127.0.0.1:5000/show1或者http://127.0.0.1:5000/show2,只会得到:
[]
15.4 高级用法
flash系统也支持对flash的内容进行分类。修改HelloWorld/server.py内容:
from flask import Flask, flash, get_flashed_messages import time app = Flask(__name__) app.secret_key = &#39;some_secret&#39; @app.route(&#39;/&#39;) def index(): return &#39;hi&#39; @app.route(&#39;/gen&#39;) def gen(): info = &#39;access at &#39;+ time.time().__str__() flash(&#39;show1 &#39;+info, category=&#39;show1&#39;) flash(&#39;show2 &#39;+info, category=&#39;show2&#39;) return info @app.route(&#39;/show1&#39;) def show1(): return get_flashed_messages(category_filter=&#39;show1&#39;).__str__() @app.route(&#39;/show2&#39;) def show2(): return get_flashed_messages(category_filter=&#39;show2&#39;).__str__() if __name__ == "__main__": app.run(port=5000, debug=True)
某一时刻,浏览器访问http://127.0.0.1:5000/gen,浏览器界面显示:
access at 1404022326.39
不过,由上面的代码可以知道,此时生成了两个flash信息,但分类(category)不同。
使用浏览器访问http://127.0.0.1:5000/show1,得到如下内容:
[&#39;1 access at 1404022326.39&#39;]
而继续访问http://127.0.0.1:5000/show2,得到的内容为空:
[]
15.5 在模板文件中获取flash的内容
在Flask中,get_flashed_messages()
默认已经集成到Jinja2
模板引擎中,易用性很强。
以上がPython が Web フレームワーク Flask を使用してプロジェクトを開発する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









PSの「読み込み」の問題は、リソースアクセスまたは処理の問題によって引き起こされます。ハードディスクの読み取り速度は遅いか悪いです。CrystaldiskInfoを使用して、ハードディスクの健康を確認し、問題のあるハードディスクを置き換えます。不十分なメモリ:高解像度の画像と複雑な層処理に対するPSのニーズを満たすためのメモリをアップグレードします。グラフィックカードドライバーは時代遅れまたは破損しています:ドライバーを更新して、PSとグラフィックスカードの間の通信を最適化します。ファイルパスが長すぎるか、ファイル名に特殊文字があります。短いパスを使用して特殊文字を避けます。 PS独自の問題:PSインストーラーを再インストールまたは修理します。

ブートがさまざまな理由によって引き起こされる可能性がある場合、「読み込み」に巻き込まれたPS:腐敗したプラグインまたは競合するプラグインを無効にします。破損した構成ファイルの削除または名前変更。不十分なプログラムを閉じたり、メモリをアップグレードしたりして、メモリが不十分であることを避けます。ソリッドステートドライブにアップグレードして、ハードドライブの読み取りをスピードアップします。 PSを再インストールして、破損したシステムファイルまたはインストールパッケージの問題を修復します。エラーログ分析の起動プロセス中にエラー情報を表示します。

「ロード」は、PSでファイルを開くときに発生します。理由には、ファイルが大きすぎるか破損しているか、メモリが不十分で、ハードディスクの速度が遅い、グラフィックカードドライバーの問題、PSバージョンまたはプラグインの競合が含まれます。ソリューションは、ファイルのサイズと整合性を確認し、メモリの増加、ハードディスクのアップグレード、グラフィックカードドライバーの更新、不審なプラグインをアンインストールまたは無効にし、PSを再インストールします。この問題は、PSパフォーマンス設定を徐々にチェックして使用し、優れたファイル管理習慣を開発することにより、効果的に解決できます。

この記事では、MySQLデータベースの操作を紹介します。まず、MySQLWorkBenchやコマンドラインクライアントなど、MySQLクライアントをインストールする必要があります。 1. mysql-uroot-pコマンドを使用してサーバーに接続し、ルートアカウントパスワードでログインします。 2。CreatedAtaBaseを使用してデータベースを作成し、データベースを選択します。 3. createTableを使用してテーブルを作成し、フィールドとデータ型を定義します。 4. INSERTINTOを使用してデータを挿入し、データをクエリし、更新することでデータを更新し、削除してデータを削除します。これらの手順を習得することによってのみ、一般的な問題に対処することを学び、データベースのパフォーマンスを最適化することでMySQLを効率的に使用できます。

羽毛の鍵は、その漸進的な性質を理解することです。 PS自体は、勾配曲線を直接制御するオプションを提供しませんが、複数の羽毛、マッチングマスク、および細かい選択により、半径と勾配の柔らかさを柔軟に調整して、自然な遷移効果を実現できます。

MySQLには、無料のコミュニティバージョンと有料エンタープライズバージョンがあります。コミュニティバージョンは無料で使用および変更できますが、サポートは制限されており、安定性要件が低く、技術的な能力が強いアプリケーションに適しています。 Enterprise Editionは、安定した信頼性の高い高性能データベースを必要とするアプリケーションに対する包括的な商業サポートを提供し、サポートの支払いを喜んでいます。バージョンを選択する際に考慮される要因には、アプリケーションの重要性、予算編成、技術スキルが含まれます。完璧なオプションはなく、最も適切なオプションのみであり、特定の状況に応じて慎重に選択する必要があります。

MySQLパフォーマンスの最適化は、インストール構成、インデックス作成、クエリの最適化、監視、チューニングの3つの側面から開始する必要があります。 1。インストール後、INNODB_BUFFER_POOL_SIZEパラメーターやclose query_cache_sizeなど、サーバーの構成に従ってmy.cnfファイルを調整する必要があります。 2。過度のインデックスを回避するための適切なインデックスを作成し、説明コマンドを使用して実行計画を分析するなど、クエリステートメントを最適化します。 3. MySQL独自の監視ツール(ShowProcessList、ShowStatus)を使用して、データベースの健康を監視し、定期的にデータベースをバックアップして整理します。これらの手順を継続的に最適化することによってのみ、MySQLデータベースのパフォーマンスを改善できます。

PSカードの読み込みインターフェイスは、ソフトウェア自体(ファイルの破損またはプラグインの競合)、システム環境(ドライバーまたはシステムファイルの破損)、またはハードウェア(ハードディスクの破損またはメモリスティックの障害)によって引き起こされる場合があります。まず、コンピューターリソースで十分かどうかを確認し、バックグラウンドプログラムを閉じ、メモリとCPUリソースをリリースします。 PSのインストールを修正するか、プラグインの互換性の問題を確認してください。 PSバージョンを更新またはフォールバックします。グラフィックカードドライバーをチェックして更新し、システムファイルチェックを実行します。上記の問題をトラブルシューティングする場合は、ハードディスク検出とメモリテストを試すことができます。
