<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Flask是一個Python編寫的Web 微框架,讓我們可以使用Python語言快速實現一個網站或Web服務。本文參考自Flask官方檔案,大部分程式碼參照自官方檔案。
首先我們來安裝Flask。最簡單的辦法就是使用pip。
pip install flask
然後開啟一個Python檔案,輸入下面的內容並執行該檔案。然後存取localhost:5000
,我們應當可以看到瀏覽器上輸出了hello world。
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'hello world' if __name__ == '__main__': app.run(host='127.0.0.1',port=5000)
我們修改程式碼中的輸出,然後檢視瀏覽器上是否有變化。如果你照做的話,可以看到什麼變化都沒有。其實Flask內建了偵錯模式,可以自動過載程式碼並顯示偵錯資訊。這需要我們開啟偵錯模式,方法很簡單,設定FLASK_DEBUG
環境變數,並將值設定為1
。或者設定app.debug=True
from flask import Flask app = Flask(__name__) app.debug=True @app.route('/') def hello_world(): return 'Hello World!' @app.route('/login') def login(): return 'Login' if __name__ == '__main__': app.run()
然後再次執行程式,會看到有這樣的輸出。這時候如果再次修改程式碼,會發現這次Flask會自動重啟。
* Restarting with stat
* Debugger is active!
* Debugger PIN: 157-063-180
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
在上面的例子裡可以看到路由的使用。如果瞭解Spring Web MVC的話,應該對路由很熟悉。路由通過使用Flask的app.route
裝飾器來設定,這類似Java的註解。
@app.route('/') def index(): return 'Index Page' @app.route('/hello') def hello(): return 'Hello, World'
如果希望獲取/article/1
這樣的路徑引數,就需要使用路徑變數。路徑變數的語法是/path/<converter:varname>
。在路徑變數前還可以使用可選的轉換器,有以下幾種轉換器。
轉換器 | 作用 |
---|---|
string | 預設選項,接受除了斜槓之外的字串 |
int | 接受整數 |
float | 接受浮點數 |
path | 和string類似,不過可以接受帶斜槓的字串 |
any | 匹配任何一種轉換器 |
uuid | 接受UUID字串 |
下面是Flask官方的例子。
@app.route('/user/<username>') def show_user_profile(username): # show the user profile for that user return 'User %s' % username @app.route('/post/<int:post_id>') def show_post(post_id): # show the post with the given id, the id is an integer return 'Post %d' % post_id
在Web程式中常常需要獲取某個頁面的URL,在Flask中需要使用url_for('方法名')
來構造對應方法的URL。下面是Flask官方的例子。
>>> from flask import Flask, url_for >>> app = Flask(__name__) >>> @app.route('/') ... def index(): pass ... >>> @app.route('/login') ... def login(): pass ... >>> @app.route('/user/<username>') ... def profile(username): pass ... >>> with app.test_request_context(): ... print url_for('index') ... print url_for('login') ... print url_for('login', next='/') ... print url_for('profile', username='John Doe') ... / /login /login?next=/ /user/John%20Doe
如果需要處理具體的HTTP方法,在Flask中也很容易,使用route
裝飾器的methods
引數設定即可。
from flask import request @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': do_the_login() else: show_the_login_form()
Web程式中常常需要處理靜態檔案,在Flask中需要使用url_for
函數並指定static
端點名和檔名。在下面的例子中,實際的檔案應放在static/
資料夾下。
url_for('static', filename='style.css')
Flask預設使用Jinja2作為模板,Flask會自動設定Jinja 模板,所以我們不需要其他設定了。預設情況下,模板檔案需要放在templates
資料夾下。
使用 Jinja 模板,只需要使用render_template
函數並傳入模板檔名和引數名即可。
from flask import render_template @app.route('/hello/') @app.route('/hello/<name>') def hello(name=None): return render_template('hello.html', name=name)
相應的模板檔案如下。
<!doctype html> <title>Hello from Flask</title> {% if name %} <h1>Hello {{ name }}!</h1> {% else %} <h1>Hello, World!</h1> {% endif %}
Flask 為我們預設定了一個 Logger,我們可以直接在程式中使用。這個Logger是一個標準的Python Logger,所以我們可以向標準Logger那樣設定它,詳情可以參考官方檔案或者我的文章Python 紀錄檔輸出。
app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')
在 Flask 中獲取請求引數需要使用request
等幾個全域性物件,但是這幾個全域性物件比較特殊,它們是 Context Locals ,其實就是 Web 上下文中區域性變數的代理。雖然我們在程式中使用的是全域性變數,但是對於每個請求作用域,它們都是互不相同的變數。理解了這一點,後面就非常簡單了。
Request 物件是一個全域性物件,利用它的屬性和方法,我們可以方便的獲取從頁面傳遞過來的引數。
method
屬性會返回HTTP方法的類似,例如post
和get
。form
屬性是一個字典,如果資料是POST型別的表單,就可以從form
屬性中獲取。下面是 Flask 官方的例子,演示了 Request 物件的method
和form
屬性。
from flask import request @app.route('/login', methods=['POST', 'GET']) def login(): error = None if request.method == 'POST': if valid_login(request.form['username'], request.form['password']): return log_the_user_in(request.form['username']) else: error = 'Invalid username/password' # the code below is executed if the request method # was GET or the credentials were invalid return render_template('login.html', error=error)
如果資料是由GET方法傳送過來的,可以使用args
屬性獲取,這個屬性也是一個字典。
searchword = request.args.get('key', '')
利用Flask也可以方便的獲取表單中上傳的檔案,只需要利用 request 的files
屬性即可,這也是一個字典,包含了被上傳的檔案。如果想獲取上傳的檔名,可以使用filename
屬性,不過需要注意這個屬性可以被使用者端更改,所以並不可靠。更好的辦法是利用werkzeug
提供的secure_filename
方法來獲取安全的檔名。
from flask import request from werkzeug.utils 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))
Flask也可以方便的處理Cookie。使用方法很簡單,直接看官方的例子就行了。下面的例子是如何獲取cookie。
from flask import request @app.route('/') def index(): username = request.cookies.get('username') # 使用 cookies.get(key) 代替 cookies[key] 避免 # 得到 KeyError 如果cookie不存在
如果需要傳送cookie給使用者端,參考下面的例子。
from flask import make_response @app.route('/') def index(): resp = make_response(render_template(...)) resp.set_cookie('username', 'the username') return resp
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()
預設的錯誤頁面是一個空頁面,如果需要自定義錯誤頁面,可以使用errorhandler
裝飾器。
from flask import render_template @app.errorhandler(404) def page_not_found(error): return render_template('page_not_found.html'), 404
預設情況下,Flask會根據函數的返回值自動決定如何處理響應:如果返回值是響應物件,則直接傳遞給使用者端;如果返回值是字串,那麼就會將字串轉換為合適的響應物件。我們也可以自己決定如何設定響應物件,方法也很簡單,使用make_response
函數即可。
@app.errorhandler(404) def not_found(error): resp = make_response(render_template('error.html'), 404) resp.headers['X-Something'] = 'A value' return resp
我們可以使用全域性物件session
來管理使用者對談。Sesison 是建立在 Cookie 技術上的,不過在 Flask 中,我們還可以為 Session 指定金鑰,這樣儲存在 Cookie 中的資訊就會被加密,從而更加安全。直接看 Flask 官方的例子吧。
from flask import Flask, session, redirect, url_for, escape, request app = Flask(__name__) @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')) # set the secret key. keep this really secret: app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
這裡簡單的介紹一下Jinja 模板的使用方法,詳細資料直接看原檔案吧。
其實Jinja 模板和其他語言和框架的模板類似,反正都是通過某種語法將HTML檔案中的特定元素替換為實際的值。如果使用過JSP、Thymeleaf 等模板,應該可以非常容易的學會使用 Jinja模板。
其實從上面的例子中我們應該可以看到Jinja 模板的基本語法了。程式碼塊需要包含在{% %}
塊中,例如下面的程式碼。
{% extends 'layout.html' %} {% block title %}主頁{% endblock %} {% block body %} <div class="jumbotron"> <h1>主頁</h1> </div> {% endblock %}
雙大括號中的內容不會被跳脫,所有內容都會原樣輸出,它常常和其他輔助函數一起使用。下面是一個例子。
<a class="navbar-brand" href={{ url_for('index') }}>Flask小例子</a>
模板可以繼承其他模板,我們可以將佈局設定為父模板,讓其他模板繼承,這樣可以非常方便的控制整個程式的外觀。
例如這裡有一個layout.html
模板,它是整個程式的佈局檔案。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>{% block title %}{% endblock %}</title> <link rel="stylesheet" href="{{ url_for('static',filename='css/bootstrap.css') }}" rel="external nofollow" /> <link rel="stylesheet" href="{{ url_for('static',filename='css/bootstrap-theme.css') }}" rel="external nofollow" /> </head> <body> <div class="container body-content"> {% block body %}{% endblock %} </div> <div class="container footer"> <hr> <p>這是頁尾</p> <script src="{{ url_for('static',filename='js/jquery.js') }}"></script> <script src="{{ url_for('static',filename='js/bootstrap.js') }}"></script> </body> </html>
其他模板可以這麼寫。對比一下物件導向程式設計的繼承概念,我們可以很容易的理解。
{% extends 'layout.html' %} {% block title %}主頁{% endblock %} {% block body %} <div class="jumbotron"> <h1>主頁</h1> <p>本專案演示了Flask的簡單使用方法,點選導航欄上的選單條檢視具體功能。</p> </div> {% endblock %}
條件判斷可以這麼寫,類似於JSP標籤中的Java 程式碼,{% %}
中也可以寫Python程式碼。下面是Flask官方檔案的例子。
<div class=metanav> {% if not session.logged_in %} <a href="{{ url_for('login') }}" rel="external nofollow" >log in</a> {% else %} <a href="{{ url_for('logout') }}" rel="external nofollow" >log out</a> {% endif %} </div>
迴圈的話可以這麼寫,和在Python中遍歷差不多。
<tbody> {% for key,value in data.items() %} <tr> <td>{{ key }}</td> <td>{{ value }}</td> </tr> {% endfor %} <tr> <td>檔案</td> <td></td> </tr> </tbody>
需要注意不是所有的Python程式碼都可以寫在模板裡,如果希望從模板中參照其他檔案的函數,需要顯式將函數註冊到模板中。可以參考這個爆棧提問。
這篇文章主要參考了Flask的官方檔案,但是隻介紹了 Flask的最基本的一部分。瞭解了這部分,我們可以用Python 搭一個小伺服器做點事情。如果希望詳細瞭解 Flask的使用用法,請關注更詳細的資料。本文就是起一個拋磚引玉的效果。
順便說,通過Flask 我也瞭解了Python 語言的執行速度。我們都知道編譯器編譯出來的程式碼執行起來要比直譯器解釋程式碼要快大約幾十倍到幾千倍不等。以前學Java的時候,感覺Java 慢,主要原因就是等待編譯時間比較長。相對來說用Python寫指令碼就很塊了,因為沒有編譯過程。
但是從Flask的執行速度來看,我切身感受到了Python 執行確實不快。舉個例子,在Spring中寫一個控制器,接受HTTP引數,並顯示到頁面上,如果程式編譯完之後,這個顯示過程基本是瞬時的。但是同樣的需求在Flask中,我居然可以感覺到明顯的延遲(大概幾百毫秒的等待時間)。所以,如果你想寫一個比較快的Web程式,還是用Java或者JVM語言吧,雖然看著土,效能確實槓槓的 。
到此這篇關於Python中的flask框架詳解的文章就介紹到這了,更多相關Python flask框架內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45