一、Flask框架介紹
使用python開發(fā)后端,目前主流的框架就是Flask和Django。其中,F(xiàn)lask是一款輕量級的Python web框架,有以下主要特點:
1. 簡單易用
Flask很簡單易用,可以快速上手開發(fā)web應用。它只依賴Werkzeug和Jinja2兩個庫,沒有象Django那樣的重量級復雜的功能。
2. 靈活
Flask非常靈活,可以適用于不同的項目規(guī)模。從簡單的"Hello World"到大型項目都可以使用Flask開發(fā)。并且它可以與更多的flask擴展結合,實現(xiàn)更豐富的功能。相對來講,Django只適合較大的工程。
3. Pythonic
Flask使用Python語言開發(fā),遵循Pythonic的設計理念,語法優(yōu)雅簡潔,具有很強的可讀性。這使得Flask非常適合學習和理解。
4. RESTful
Flask天生支持RESTful風格的web服務開發(fā)。HTTP一級支持,簡單的URL規(guī)則等使其非常適合構建REST API。
5. 擴展性強
Flask最重要的一個特點就是擁有豐富的擴展,幾乎涵蓋了web開發(fā)所有的功能,如:ORM(Flask-SQLAlchemy)、表單驗證(Flask-WTF)、文件上傳(Flask-Uploads)、用戶認證(Flask-Login)等。這些擴展可以根據(jù)需要很容易集成到Flask應用中。需要什么插件,就安裝什么插件。
6. 部署方便
Flask的應用十分簡單,甚至一個py文件就行。它支持與各種Web服務器兼容,如WSGI服務器、Nginx和uWSGI等。
7. 社區(qū)優(yōu)秀
Flask擁有龐大的社區(qū),官方文檔資料也比較齊全。幾乎所有的問題都可以在網(wǎng)上找到答案。
所以,總的來說,F(xiàn)lask是一個簡單、靈活、易于理解、可擴展性強的Python web框架。它適用于學習、 小型項目以及復雜項目。具有非常優(yōu)秀的社區(qū)資源和生態(tài)環(huán)境。
二、RESTFul協(xié)議特點
1. 基于HTTP
RESTful API基于HTTP協(xié)議,使用HTTP方法為資源定義操作。如GET用于讀取,POST用于創(chuàng)建,PUT用于更新,DELETE用于刪除等。有的API接口,無論是讀取還是更新,都統(tǒng)一使用POST方法,而把實際的動詞包含在URL里,如'/data/delete'。
2. 無狀態(tài)
RESTful API是無狀態(tài)的,它不存儲任何客戶端上下文信息。每個請求必須包含請求所需要的所有信息,服務器根據(jù)請求進行響應。
3. 層次結構
RESTful API使用統(tǒng)一的接口訪問命名空間中的所有資源。這些資源可以被層次化,形成資源的樹形結構。
4. 使用URL定位資源
每個資源都有一個唯一的URL來指定和定位,這一點和文件夾路徑原理是一樣的。
5. 可緩存
RESTful API響應可以是可緩存的,這可以提高效率和性能。緩存可以存在于服務器端、客戶端或代理服務器。這一點對于頻繁請求某一資源時很有幫助。
6. 統(tǒng)一接口
?RESTful API將所有資源通過統(tǒng)一的接口來訪問和操作。這簡化了整個系統(tǒng)。
7. 跨語言兼容
RESTful API返回的通常為JSON或XML格式。這使其對各種語言和平臺更易于實現(xiàn)和兼容。
REST是一種優(yōu)秀的開發(fā)思路和規(guī)范,但我們在實際開發(fā)時也要辯證來看。規(guī)范和通用的東西必然在靈活性上有所不足。如果我們開發(fā)的是對外的、通用的接口,那么REST是一個好的選擇。但如果這個接口只對內(nèi)部提供,則不必嚴格按照REST協(xié)議來。因為實際的業(yè)務往往是復雜的、具體的和相對固定的。那么針對性地提供一些接口,會讓前端開發(fā)(調用者)更容易。某種程度,也可以減少一定的http請求次數(shù)。如某個頁面有幾十個數(shù)據(jù)需要請求,按照REST風格來可能需要請求幾十個接口,而我們可以設計一個統(tǒng)一接口將全部信息返回(有點夸張了)。
三、路由
1、路由的概念
百度百科的解釋是:“路由(routing)是指分組從源到目的地時,決定端到端路徑的網(wǎng)絡范圍的進程”。在TCP/IP協(xié)議里,路由器的工作就是將不同的信息根據(jù)ip地址進行分發(fā)。而在web開發(fā)中,概念也基本一致。即將前面提到的url與資源進行一種映射,請求相應的url則獲取對應資源。而建立這種映射的過程就叫注冊路由。
2、兩種路由注冊方式
from flask import Flask
app = Flask(__name__)
# 方法一
@app.route('/hello')
def hello():
return 'hello world'
if __name__ == '__main__':
app.run('0.0.0.0', 5555)
?第一種方法是利用了python裝飾器的特性,route方法內(nèi)部仍然是調用add_url_rule。本質是一樣的,只是裝飾器看起來更優(yōu)雅。
關于裝飾器的解釋可以參考下文Python 裝飾器_function databaseerrorwrapper.__call__.<locals>.in_Jiangugu的博客-CSDN博客
from flask import Flask
app = Flask(__name__)
def hello():
return 'hello world'
# 方法二
app.add_url_rule('/hello', view_func=hello)
if __name__ == '__main__':
app.run('0.0.0.0', 5555)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
四、Request請求對象
以百度搜索關鍵詞python為例,可以通過后臺查看請求對象包含的信息
?
可以看到,雖然我們只輸入了一個python,但實際的請求包含了很豐富的信息。如請求頭里包含的請求地址、方法 ,請求體里包含的關鍵字等。在一些需要登陸的網(wǎng)站,往往還需要攜帶cookies。本文主要還是講解利用flask搭建后端,主要作為響應端。即如何響應請求,關于更多request的介紹請參考下文。
Python 網(wǎng)絡開發(fā)基礎之Requests_request是技術還是庫_Jiangugu的博客-CSDN博客
五、Response響應對象
響應對象和請求對象一樣,除了“內(nèi)容”部分,還會包含諸多其他信息。常見的如content-type、status_code。在flask里,必須指定的是內(nèi)容部分,其余均有默認值。
1、content-type
默認的content-type是html,那么返回的字符串就會按照html的格式去解析,因此前端顯示為空。
@app.route('/test')
def test():
return '<html></html>'
如果想顯示這段文本,則手動指定content-type即可
@app.route('/test')
def test():
header = {
'content-type': 'text/plain'
}
return '<html></html>', header
?
返回一個網(wǎng)頁的示例
@web.route('/square/<p>', methods=['GET'])
def square(p):
"""
:param p:
:return: 返回的是一個html
"""
return render_template('test.html', result=int(p)**2)
?這是前端部分(樣式CSS和腳本JS沒有展開,本文主要講解后端和接口)。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>'測試網(wǎng)頁'</title>
</head>
<body>
<div>
<p style="color: red">計算結果是:{{ result }}</p>
</div>
</body>
</html>
?
?而對于API來說,content-type為'application/json',即要求調用者按照json格式去解析。
2、狀態(tài)碼
常見狀態(tài)碼包括200(請求成功)、301(重定向)、404(未找到資源)、500(服務器內(nèi)部錯誤)。這里需要強調的是,狀態(tài)碼只是一種約定。你完全可以約定請求成功是404,只要事先和請求方約定好。
雖然瀏覽器報錯,但內(nèi)容仍正常顯示。此外,在接口開發(fā)中,可能出現(xiàn)的情況會很多。僅有的幾個狀態(tài)碼一般都是不夠用的。往往會在內(nèi)容content里再約定一個如status這樣的變量,約定1是成功,2是沒有權限,3是參數(shù)不夠,4是數(shù)據(jù)范圍超出……
from flask import Flask
import json
app = Flask(__name__)
@app.route('/test/<nums>')
def test(nums):
dt = nums.split(',')
header = {
'content-type': 'application/json',
}
if len(dt) > 10:
return json.dumps({'status': 4, 'msg': '數(shù)據(jù)長度不能超過10'}), 500, header
else:
return json.dumps({'status': 1, 'result': 111}), 200, header
if __name__ == '__main__':
app.run('0.0.0.0', port=8000, debug=True)
?
六、表單
除了URL里可以攜帶參數(shù),還有一種常見的傳參方式就是通過表單,如登錄和注冊頁面填寫的賬號、密碼等信息。后端如何接收這些信息呢?
<html>
<head>
<title>測試網(wǎng)頁</title>
<link rel="stylesheet" type="text/css" href="static/login.css"/>
<link rel="shortcut icon"
href="{{ url_for('static', filename='pics/logo.png') }}">
</head>
<body>
<div id="main">
<div id="top">
<img src={{url_for('static', filename='pics/pure_logo.png')}} id="logo">
</div>
<div id="bottom">
<form method="POST">
<p class="titleofinput">用戶名: </p>
<input type="text" name="username" class="input" autocomplete="off" placeholder="請輸入用戶名" required>
<p class="titleofinput">密碼: </p>
<input type="password" name="password" class="input" autocomplete="off" placeholder="請輸入密碼" required>
<br>
<button type="submit" id="submit">登錄</button>
</form>
</div>
</div>
</body>
</html>
這個簡單的登錄界面示例代碼中,輸入用戶名和密碼使用的是<input>標簽且存在于<form>里。而它們都有一個name屬性,因此后端可以通過這個屬性獲得對應傳遞過來的值。
from flask import request, url_for, redirect, render_template
from flask_login import login_user
from model.user import User
from . import web
@web.route('/login', methods=['GET', 'POST'])
def login():
username = request.form.get('username')
password = request.form.get('password')
if request.method == 'POST':
# 自定義的user模型,將具體的校驗方法封裝其中,也可以直接粗暴地寫在這里
user = User.query.filter_by(username=username).first()
if user and user.check_password(password):
# 將用戶登錄票據(jù)寫入客戶端cookies, remember開啟默認保存365天
login_user(user, remember=True)
return redirect(url_for('web.do'))
else:
return '用戶名或密碼錯誤'
return render_template('login.html')
七、其他零散知識點
1、IP地址
我們的app在綁定地址時,可以寫網(wǎng)卡的實際地址,如192.168.0.111(固定地址,地址改變時需同步更改),也可以寫127.0.0.1(只允許本機訪問),還可以寫0.0.0.0。一般我們在開發(fā)的時候,隨便寫哪個都可以,因為都是本機訪問且地址不會變。但如果地址可能會變,同時正式部署后要允許其他計算機訪問,就只能寫0.0.0.0。
2、端口
原則上,端口可以在1~65535范圍內(nèi)任意指定,只要不與已有的端口沖突即可。如22是ssh通訊端口,3306是數(shù)據(jù)庫端口。而web端口默認是80,即使用默認端口時,瀏覽器訪問可以不指定端口。
3、調試模式
后端開發(fā)是一個交互性很強的工作,需要一邊調整一邊看結果。因此,如果每次修改代碼都需要重啟應用的話會很浪費時間。在flask里只需要打開調試模式即可實現(xiàn)類似監(jiān)聽的功能,代碼的修改能立刻應用。
app.run('0.0.0.0', 8000, debug=True)
4、參數(shù)配置
一個優(yōu)秀的web服務,離不開諸多參數(shù)配置。如前面提到的端口號、調試模式等。實際上很多代碼工程都需要配置參數(shù),而一個好的參數(shù)配置需要具備“可讀性強”,“易修改”等特點。因此,最好的方式就是在一個統(tǒng)一的地方,統(tǒng)一對參數(shù)進行定義和賦值,在整個工程其他地方使用定義的變量名。這里有兩種方式推薦,其一是配置系統(tǒng)環(huán)境變量,然后在代碼里通過os.environ.get('變量名')。第二種方法是創(chuàng)建一個配置文件,如config.py,在這個文件里配置一些參數(shù),如DEBUG=True,注意變量名需全部大寫。
# 加載配置模塊
app.config.from_object('config')
# 調用相應配置參數(shù)
app.run('0.0.0.0', debug=app.config['DEBUG'])
5、重定向
有一些資源暫時沒有或不想讓別人訪問,除了拋出404,還可以重定向。即建議請求者重新請求一個地址。
@app.route('/test')
def test():
header = {
'content-type': 'text/plain',
'location': 'https://www.baidu.com'
}
return '<html></html>', 301, header
6、傳參
(1)多參數(shù)傳參
我們在上面的案例中,參數(shù)是直接跟在url后的。那是因為參數(shù)只有一個,不太容易引起誤解。如果查詢參數(shù)較多,一般可以使用以下方式
from flask import request
import json
@app.route('/plus')
def plus():
a = request.args['a']
b = request.args['b']
header = {
'content-type': 'application/json',
}
return json.dumps({'status': 1, 'result': int(a) + int(b)}), 200, header
?
(2)數(shù)組傳參
在調用API接口時,有時會需要傳遞一個較大的數(shù)據(jù)。這時候就不適合將數(shù)據(jù)作為查詢參數(shù)添加到url里。一方面會導致url可讀性較差,同時,url也會有長度限制(因瀏覽器,服務器等不同,一般限制幾千個字符)。此時,可以將數(shù)據(jù)放到請求體里。
from flask import Flask, request
import json
app = Flask(__name__)
@app.route('/test/')
def test():
dt = request.json['data']
header = {
'content-type': 'application/json',
}
if len(dt) > 10:
return json.dumps({'status': 4, 'msg': '數(shù)據(jù)長度不能超過10'}), 400, header
else:
return json.dumps({'status': 1, 'result': sum(dt)}), 200, header
if __name__ == '__main__':
app.run('0.0.0.0', port=5555, debug=True)
?7、Cookie
由于http請求是沒有記憶的,每次請求都是獨立沒有上下文關聯(lián)的。但有時我們需要這種上下文關聯(lián),比如記錄登錄信息、購物網(wǎng)站的購物車、搜索記錄等。記錄這種信息的載體就是Cookie,它是由服務器生成并寫入訪問客戶端的??蛻舳嗽谙乱淮蔚脑L問中就會攜帶該信息,以便繼續(xù)對話。Cookie是以鍵值對的形式存儲的,除了key-value的信息,一般還包括允許訪問的域名、有效期等信息。使用flask框架的服務可以通過以下方式生成Cookie
from flask import make_response
@app.route('/')
def index():
# 這里快速構造了一個response對象,和前面的一樣
resp = make_response('Hello')
# 有效期1000秒
resp.set_cookie('username', 'john', 1000)
return resp
?訪問相應的視圖函數(shù),此時瀏覽器已經(jīng)被寫入Cookie。
?文章來源地址http://www.zghlxwxcb.cn/news/detail-507062.html文章來源:http://www.zghlxwxcb.cn/news/detail-507062.html
?
到了這里,關于Flask基礎及常見問題整理的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!