1. 程式人生 > >Flask 快速入門

Flask 快速入門

Flask標誌

Flask是一個Python編寫的Web 微框架,讓我們可以使用Python語言快速實現一個網站或Web服務。本文參考自Flask官方文件,大部分程式碼引用自官方文件。

安裝Flask

首先我們來安裝Flask。最簡單的辦法就是使用pip。

pip install flask

然後開啟一個Python檔案,輸入下面的內容並執行該檔案。然後訪問localhost:5000,我們應當可以看到瀏覽器上輸出了Hello Flask!

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello_world
():
return 'Hello Flask!' if __name__ == '__main__': app.run()

快速開始

除錯模式

我們修改程式碼中的輸出,然後檢視瀏覽器上是否有變化。如果你照做的話,可以看到什麼變化都沒有。其實Flask內建了除錯模式,可以自動過載程式碼並顯示除錯資訊。這需要我們開啟除錯模式,方法很簡單,設定FLASK_DEBUG環境變數,並將值設定為1

然後再次執行程式,會看到有這樣的輸出。這時候如果再次修改程式碼,會發現這次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

構造URL

在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方法

如果需要處理具體的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 物件

Request 物件是一個全域性物件,利用它的屬性和方法,我們可以方便的獲取從頁面傳遞過來的引數。

method屬性會返回HTTP方法的類似,例如postgetform屬性是一個字典,如果資料是POST型別的表單,就可以從form屬性中獲取。下面是 Flask 官方的例子,演示了 Request 物件的methodform屬性。

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))

Cookies

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

重定向和錯誤

redirectabort函式用於重定向和返回錯誤頁面。

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

Sessions

我們可以使用全域性物件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') }}"/>
    <link rel="stylesheet" href="{{ url_for('static',filename='css/bootstrap-theme.css') }}"/>

</head>
<body>

<div class="container body-content">
    {% block body %}{% endblock %}
</div>

<div class="container footer">
    <hr>
    <p>這是頁尾</p>
</div>

<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') }}">log in</a>
  {% else %}
    <a href="{{ url_for('logout') }}">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語言吧,雖然看著土,效能確實槓槓的 。

最後,我寫了一個小練習,試了試Flask 的基本功能,如果有興趣可以上我的Github檢視程式碼。

我的程式碼

相關推薦

Flask 快速入門

Flask是一個Python編寫的Web 微框架,讓我們可以使用Python語言快速實現一個網站或Web服務。本文參考自Flask官方文件,大部分程式碼引用自官方文件。 安裝Flask 首先我們來安裝Flask。最簡單的辦法就是使用pip。 p

【先驗知識歸納】Flask快速入門

out .org variable quick 程序 name body table 知識 來源:快速入門 — Flask 0.10.1 文檔 路由 路由用來關聯URL與程序函數:@app.route(‘/hello‘) 動態URL(含參數的URL)使函數可以獲得UR

flask-帶你快速入門

flask 實例 flask-web 函數 應用 一個小應用創建一個Python文件:hello.pyfrom flask import Flask app = Flask(__name__) #app是程序實例,一個項目只能有一個程序實例@app.route(‘/‘) #路由裝飾

Flask系列----快速入門實戰解析(上篇)

Flask入門 Flask並不是小白就能隨意入門的,需要基礎知識。例如: Python基礎 網路基礎 Jinja2模板引擎和Werkzeug WSGI套件 工具的使用(PyCharm) 所以,小白請謙虛,請Google不會的專業名稱!我

Flask-SQLAlchemy 快速入門

一個最小的應用 對於通常情況,只有一個 Flask 應用,你需要做的全部就是建立你的 Flask 應用, 選擇載入你的配置,然後在建立SQLALchemy時把應用傳遞給它。 一旦建立,這個物件會包含sqlalchemy和sqlalchemy.orm中 的所有函式和助手。此外,它還提供了一個名為Model

Flask---框架快速入門

環境區域性變數內幕如果你想理解其工作機制及如何利用環境區域性變數實現自動化測試,請閱讀此節,否則可跳過。Flask 中的某些物件是全域性物件,但卻不是通常的那種。這些物件實際上是特定環境的區域性物件的代理。雖然很拗口,但實際上很容易理解。想象一下處理執行緒的環境。一個請求傳入,Web 伺服器決定生成一個新執行

day39-Spring 12-Spring的JDBC模板:快速入門

pri 哪些 困難 ces 5.0 使用 只需要 common commons Spring AOP的關鍵是它的底層的原理和思想,配置和使用並不是十分困難.AOP本身就是一個思想,是面向對象的延伸,不是用來替換面向對象的,而是用來解決面向對象中的一些問題的.在最初的時候提出

vuex2快速入門

for nbsp mar lin ext mac os cnblogs value san #建立store.jsimport Vue from ‘vue‘; import Vuex from ‘vuex‘; Vue.use(Vuex) export d

快速入門系列--WCF--07傳輸安全、授權與審核

最大的 緩存 ims cut 常見 曾經 strong 這一 set 這部分主要涉及企業級應用的安全問題,一般來說安全框架主要提供3個典型的安全行為:認證、授權和審核。除了典型的安全問題,對於一個以消息作為通信手段的分布式應用,還需要考慮消息保護(Message Prote

快速入門系列

body 現在 安全 behavior 需求 discovery 中心 驗證 溝通 最後一章將進行WCF擴展和新特性的學習,這部分內容有一定深度,有一個基本的了解即可,當需要自定義一個完整的SOA框架時,可以再進行細致的學習和實踐。 服務端架構體系的構建主要包含接下來

快速入門系列--WCF--02消息、會話與服務寄宿

abc align bsp 不同的 cpu .org 程序 伸縮 網絡 經過WCF基礎的ABC學習,已經可以構建簡單的WCF的服務,使用不同的服務地址和綁定類型,根據業務提供所需的服務契約。但不禁想問,服務所使用的消息報文是什麽樣的形式麽?蘊含什麽樣內容呢?WCF服務是否支

python 基本語法速覽,快速入門

我們 method adding ger monk use gre 數據類型 struct https://zhuanlan.zhihu.com/p/24536868 學習參考於這個博文。 我做一個筆記。 關於python一些常用的語法快速的預覽,適合已經掌握一門編程語

Django REST framework 的快速入門教程

ret turn ads 使用 blog 所有 定義 想去 cti CRM-API項目搭建 序列器(Serializers) 首先,我們來定義一些序列器。我們來創建一個新的模塊(module)叫做 crm/rest_searializer.py ,這是我們用來描述數據是如何

Celery 分布式任務隊列快速入門

ade sunday reat 失敗 繼續 complete port 機器 single Celery介紹和基本使用 在項目中如何使用celery 啟用多個workers Celery 定時任務 與django結合 通過django配置celery period

Unity快速入門

小冰 教程 應該 arp nbsp 2.3 入門 模擬操作 飛機 1.熟悉基本操作。 最權威的應該是官方出品,158元的Unity官方教程,其他的基礎操作視頻 lynda 的5.0 ,5.4都可以 2.熟悉簡單例子,將API熟悉一下啊,這個過程中,背誦API是捷徑。 2

Vue.js——60分鐘快速入門

attribute 否則 style屬性 快速 基於 oid creat get rac Vue.js是當下很火的一個JavaScript MVVM庫,它是以數據驅動和組件化的思想構建的。相比於Angular.js,Vue.js提供了更加簡潔、更易於理解的API,使得我們能

Redis快速入門

pool har 語法 ansi 使用 https 測試的 對象 sta Redis快速入門 一、簡介 Redis是一個開源的使用ANSI C語言編寫、遵守BSD協議、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的A

快速入門系列--WebAPI--03框架你值得擁有

let lan 最重要的 reason cnblogs err 註意 解釋 max 接下來進入的是俺在ASP.NET學習中最重要的WebAPI部分,在現在流行的互聯網場景下,WebAPI可以和HTML5、單頁應用程序SPA等技術和理念很好的結合在一起。所謂ASP.N

快速入門系列--WebAPI--01基礎

簡單例子 codec 應該 sem ons 請求重定向 選擇 char 阻止 ASP.NET MVC和WebAPI已經是.NET Web部分的主流,剛開始時兩個公用同一個管道,之後為了更加的輕量化(WebAPI是對WCF Restful的輕量化),WebAPI使用了新的管道

快速入門系列--MVC--06視圖

出版 value 快速入門 stream 類型 path .cn esc eba 到了View的呈現板塊,感覺ASP.NET MVC的學習也進入了尾聲,還是比較開心的,畢竟也有了不小收獲。這部分內容相對比較簡單,因為之前還專門學習過如何結合HTML5與MVC框架。前