Flask-論壇開發-4-知識點補充
對Flask感興趣的,可以看下這個視頻教程:http://study.163.com/course/courseLearn.htm?courseId=1004091002
1. WTForms 表單使用
WTForms
是一個支持多 web
框架的一個插件,主要功能有兩個:第一個是做表單的驗證,驗證用戶提交上來的信息是否合法,第二個是模板渲染。
1.1 WTForms 表單驗證的基本使用
使用 WTForms
進行表單驗證,會更好的管理我們的代碼和項目結構,還可以大大提高開發項目時的效率。WTForms
功能強大,將表單定義成一個類,可以實現對表單字段的豐富限制。
使用 WTForms
實現表單驗證的功能,主要有以下步驟:
從
wtforms
中導入Form
這個類,以及相關字段的數據類型from wtforms import From,StringField,IntegerField,FileField # Form 是一個基類,StringField 用來驗證 String 類型的數據
從
wrforms.validators
導入一些限制對象(如長度限制)from wrforms.validators import Length,EqualTo # # wrforms.vaildators 是一個驗證器,包含 Length 在內的多種驗證限制,Length 則專門對參數的長度進行驗證,EqualTo 指定必須要和某個值相等
創建表單類並繼承自
Form
,定義相關字段class RegistForm(Form): # 該類用來驗證表單中傳遞的參數,屬性名和參數名必須一致 username = StringField(validators=[Length(min=3,max=10,message=‘用戶名長度必須在3到10位之間‘)]) # StringField 必須傳入關鍵字參數 validators,且 validators 是一個 List 類型(此處僅對長度作驗證) password = StringField(validators=[Length(min=6,max=16)]) password_repeat = StringField(validators=[Length(min=6,max=16),EqualTo(‘password‘)]) # 驗證長度和相等
在視圖函數中使用該 RegistForm
form = RegistForm(request.form) # request.form 會拿到所有提交的表單信息 if form.validate(): # form.validate() 方法會匹配表單信息並返回 True 或 False return ‘註冊成功!‘ else: return ‘註冊失敗!‘
完整代碼如下:
# regist.html
<form action="" method="post">
<table>
<tbody>
<tr>
<td>用戶名:</td>
<td><input type="text" name="username"></td>
</tr>
<tr>
<td>密碼:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td>確認密碼:</td>
<td><input type="password" name="password_repeat"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="點擊提交"></td>
</tr>
</tbody>
</table>
</form>
# 後端程序
from wtforms import Form,StringField
from wtforms.validators import Length,EqualTo
class RegistForm(Form):
username = StringField(validators=[Length(min=3,max=10,message=‘輸入的用戶名不符合長度規範‘)])
password = StringField(validators=[Length(min=6,max=16)])
password_repeat = StringField(validators=[Length(min=6,max=16),EqualTo(‘password‘)])
@app.route(‘/regist/‘,methods=[‘GET‘,‘POST‘])
def regist():
if request.method == ‘GET‘:
return render_template(‘regist.html‘)
else:
form = RegistForm(request.form)
if form.validate():
return ‘註冊成功‘
else:
print(form.errors)
for message in form.errors:
return ‘註冊成功‘
1.2 WTForms 的相關驗證器
除了上面使用到的兩個驗證器(StringField
和EqualTo
)外,WTForms 中還有很多常用的驗證器:
Email
:驗證上傳的數據是否為郵箱(格式)email = StringField(validators=[email()])
EqualTo
:驗證上傳的數據是否與另一個字段相等,常用在註冊時的兩次密碼輸入上password_repeat = StringField(validators=[Length(min=6,max=16),EqualTo(‘password‘)])
InputRequired
:該字段必須輸入參數,且只要輸入了,那麽該字段就是True
。如果不是特數據情況,應該使用InputRequired
password = StringField(validators=[InputRequired()]) # 不管你的值是什麽,只要輸入了就是 True
Length
:長度限制,由min
和max
兩個值進行限制password = StringField(validators=[Length(6,16)])
NumberRange
:數字的區間,由min
和max
兩個值進行限制(包括min
和max
)age = IntegerField(validators=[NumberRange(12,100)])
Regexp
:自定義正則表達式,比如手機號碼的匹配phone = StringField(validators=[Regexp(r‘1[34578]\d{9}‘)])
URL
:必須要是URL
的形式homepage = StringField(validators=[URL()])
UUID
:驗證UUID
uuid = StringField(validators=[UUID()])
註意在使用驗證器的時候,後面要加上 ()
。
1.3 自定義驗證器
如果以上介紹的驗證器不滿足項目當中的需求,那麽還可以根據需求自定義相關的驗證器。如果想要對表單中的某個字段進行更加細致的驗證,那麽可以根據需求對該字段定進行單獨的驗證,步驟如下:
- 在表單驗證類中定義一個方法,方法的命名規則為:
validate_字段名(self,field)
。 - 在方法中使用
field.data
獲取到用戶上傳到這個字段上的值。 - 對於驗證的判斷:若驗證成功,可以什麽都不做;若驗證失敗,則必須跑出
wtforms.validators.ValidationError
異常,並填入驗證失敗的原因。
示例代碼如下所示:
from wtforms import Form,StringField
from wtforms.validators import Length,ValidationError
class LoginForm(Form):
captcha = StringField(validators=[Length(4,4)])
def validate_captcha(self,field): # 用 validate_captcha 來指定該驗證器是針對 captcha 字段的
if field.data != ‘aw7e‘:
raise ValidationError(‘驗證碼輸入錯誤!‘)
1.4 WTForms 渲染模板
這個功能可以讓我們的前端代碼少寫一點點,但是實際上用處不大。主要使用方法如下:
在
forms
文件中定義一個表單類:class SettingsForms(Form): username = StringField(validators=[Length(4,10)])
在視圖函數中返回模板時傳遞相關參數:
@app.route(‘/settings/‘,methods=[‘GET‘,‘POST‘]) def Settings(): if request.method == ‘GET‘: form = SettingsForms() return render_template(‘settings.html‘,my_form=form) else: pass
在前端模板中調用
<form action="" method="post"> <table> <tbody> <tr> <td>{{ my_form.username.label }}</td> <td>{{ my_form.username() }}</td> </tr> <tr> <td></td> <td><input type="submit" value="提交"></td> </tr> </tbody> </table> </form>
其中,第五第六兩行相當於:
<td>用戶名:</td> <td><input type="text" name=‘username‘></td>
實際上,這個功能在生產環境中幾乎沒有任何作用,很雞肋。
2. 文件上傳和訪問
2.1 文件上傳
上傳文件時需要註意以下幾點:
在模板中,
form
表單內,要指定encotype=‘multipart/form-data‘
才能實現文件的上傳:<form action="" method="post" enctype="multipart/form-data"> ... </form>
在後臺獲取文件,需要使用
request.files.get(‘標簽名‘)
才能獲取到上傳的文件:avatar = request.files.get(‘avatar‘)
保存文件使用
avatar.save(路徑)
實現,推薦在保存文件時先對文件進行安全封裝:from werkzueg.utils import secure_filename import os UPLOAD_PATH = os.path.join(os.path.dirname(__file__),‘images‘) # UPLOAD_PATH = 當前路徑/images avatar.save(UPLOAD_PATH,secure_filename(avatar.filename))
後臺完整代碼如下:
from werkzeug.utils import secure_filename import os UPLOAD_PATH = os.path.join(os.path.dirname(__file__),‘images‘) # 定義文件保存路徑:UPLOAD_PATH = 當前路徑/images @app.route(‘/upload/‘,methods=[‘GET‘,‘POST‘]) def upload(): if request.method == ‘GET‘: return render_template(‘upload.html‘) else: avatar = request.files.get(‘avatar‘) filename = secure_filename(avatar.filename) # 對文件名進行安全過濾 avatar.save(os.path.join(UPLOAD_PATH,filename)) desc = request.form.get(‘desc‘) print(desc) return ‘上傳成功!‘
2.2 文件訪問
實現了文件上傳,那麽用戶肯定會需要對文件進行訪問。在 Flask
中,實現文件的訪問必須要定義一個單獨的 url
與視圖函數的映射,並且要借助 send_from_directory
方法返回文件給客戶端。
從
flask
導入send_from_directory
from flask import send_from_directory
定義視圖函數並映射到文件的 url
UPLOAD_PATH = os.path.join(os.path.dirname(__file__),‘images‘) @app.route(‘/getfile/<filename>/‘) def getfile(filename): return send_from_directory(UPLOAD_PATH,filename) # send_from_directory 要傳入路徑和文件名 # 用戶可以訪問 http://domainname/filename 對文件進行訪問
2.3 使用驗證器對驗證上傳的文件
在驗證文件的時候,同樣要定義一個驗證的類,然後用該驗證類去驗證上傳的文件。主要分為以下幾個步驟:
導入
FileField
和文件驗證器:FileRequired
、FileAllowed
from forms import FileField from flask_wtf.file import FileRequired,FileAllowed # 註意這兩個針對文件的驗證器是從 flask_wtf_file 中導入的,而不是從之前的 wtforms.validators 中導入
定義表單類並繼承自
Form
,然後定義相關字段class UpLoadForm(Form): avatar = FileField(validators=[FileRequired(),FileAllowed([‘jpg‘,‘png‘,‘gif‘])]) # FileRequired() 要求必須傳入文件,FileAllowed() 則指定了允許的文件類型 desc = StringField(validators=[InputRequired()])
在主
app
文件中引用from werkzeug.datastructures import CombinedMultiDict # CombinedMultiDict 用來合並兩個不可變的 dict form =UpLoadForm(CombinedMultiDict([request.form,request.files])) # 傳入用戶提交的信息,其中 request.form 是表單中的信息,request.files 是上傳的文件
完整代碼如下:
# forms.py 文件 from wtforms import Form,StringField,FileField from flask_wtf.file import FileRequired,FileAllowed class UpLoadForm(Form): avatar = FileField(validators=[FileRequired(),FileAllowed([‘jpg‘,‘png‘,‘gif‘])]) desc = StringField(validators=[InputRequired()]) # 主 app 文件 from forms import UpLoadForm from werkzeug.utils import secure_filename from werkzeug.datastructures import CombinedMultiDict import os UPLOAD_PATH = os.path.join(os.path.dirname(__file__),‘images‘) @app.route(‘/upload/‘,methods=[‘GET‘,‘POST‘]) def upload(): if request.method == ‘GET‘: return render_template(‘upload.html‘) else: form =UpLoadForm(CombinedMultiDict([request.form,request.files])) if form.validate(): avatar = request.files.get(‘avatar‘) filename = secure_filename(avatar.filename) avatar.save(os.path.join(UPLOAD_PATH,filename)) desc = request.form.get(‘desc‘) print(desc) return ‘上傳成功!‘ else: return ‘上傳失敗!‘
3. Cookie 的使用
3.1 設置 Cookie
設置 Cookie
是 Response
類中有的方法,用法是:在視圖函數中
resp = Response(‘MYYD‘) # 創建一個 Response 對象,傳入的字符串會被顯示在網頁中
resp.set_cookie(‘username‘,‘myyd‘)
return resp
其中,set_cookie
() 中的參數有:
key 鍵
value 值
max_age IE8 以下不支持,優先級比 expires 高
expires 幾乎所有瀏覽器都支持,必須傳入 datetime 的數據類型,並且默認加 8 個小時(因為我們是東八區)
path 生效的 URL,‘/‘ 代表該域名下所有 URL 都生效,一般默認就好
domian 域名,若沒設置,則只能在當前域名下使用
secure 默認 False,若改為 True 則只能在 https 協議下使用
httponly 默認 False,若改為 True 則只能被瀏覽器所讀取,不能被 JavaScript 讀取(JavaScript可以在前端處理一些簡單邏輯)
使用時依次傳入即可,如果有些選項要跳過則需要指定一下參數名。
完整代碼如下所示:
from flask import Flask,Response
app = Flask(__name__)
@app.route(‘/‘)
def hello_world():
resp = Response(‘首頁‘)
resp.set_cookie(‘username‘,‘MYYD‘)
return resp
if __name__ == ‘__main__‘:
app.run()
3.2 刪除 Cookie
刪除 Cookie
時需要另外指定一條 URL
和視圖函數,也是使用 Response
來創建一個類,並使用 resp.delete_cookie()
來完成這個需求。代碼如下所示:
from flask import Flask,Response
app = Flask(__name__)
@app.route(‘/delCookie/‘)
def delete_cookie():
resp = Response(‘刪除Cookie‘)
resp.delete_cookie(‘username‘)
return resp
if __name__ == ‘__main__‘:
app.run()
3.3 設置 Cookie 的有效期
設置 Cookie
的有效期,可以有兩種方法:使用 max_age
或 expires
。
使用
max_age
使用 max-age 時要註意,max-age 不支持 IE8 及以下版本的瀏覽器,並且只能相對於現在的時間往後進行推遲(單位是秒s),而不能指定具體的失效時間。使用方法如下代碼所示:
resp.set_cookie(‘username‘,‘myyd‘,max_age=60) # 設置該 cookie 60s 之後失效。
使用
expires
使用
expires
時要註意,必須要使用格林尼治時間,因為最後會自動加上 8 小時(中國是東八區)。expires
的兼容性要比max_age
要好,盡管在新版的http
協議中指明了expires
要被廢棄,但現在幾乎所有的瀏覽器都支持expires
。expire
設置失效時間,可以針對當前時間往後推移,也可以指定某一個具體的失效時間。具體如下所示:針對當前時間推移
from datetime import datetime,timedelta expires = datetime.now() + timedelta(days=30,hours=16) # 當下時間往後推移 31 天失效,註意這裏給的參數是減了 8 小時的 resp.set_cookie(‘username‘,‘MYYD‘,expires=expires)
指定具體日期
from datetime import datetime resp = Response(‘首頁‘) expires = datetime(year=2018,month=12,day=30,hour=10,minute=0,second=0) # 實際上的失效時間是 2018-12-30-18:0:0 resp.set_cookie(‘username‘,‘MYYD‘,expires=expires) return resp
其他註意事項
此外,還要註意幾點:
- 當同時使用
max_age
和expires
的時候,會優先使用max_age
指定的失效時間 - 若同時不使用
max_age
和expires
的時候,默認的cookie
失效時間為瀏覽器關閉的時間(而不是窗口關閉的時間) expires
要設置為格林尼治時間,同時導入datetime.datetime
和datetime.timedelta
- 當同時使用
4. RFCS
防範 CSRF 攻擊的措施:
實現:在返回一些危險操作的頁面時,同時返回一個 csrf_token
的 cookie
信息,並且在返回的頁面表單中也返回一個帶有 csrf_token
值的 input
標簽。
原理:當用戶提交該表單時,若表單中 input
標簽的 csrf_token
值存在並且和 cookie
中的 csrf_token
值相等則允許操作;若不滿足該條件,則操作不被允許。
原因:因為 csrf_token
這個值是在返回危險操作頁面時隨機生成的,黑客是無法偽造出相同的 csrf_token
值的,因為黑客不能操作非自己域名下的 cookie
,即不知道 cookie
中的 csrf_token
值的內容。
具體實現:
主app文件:
- from flask_wtf import CSRFProtect
- CSRFProtect(app)
模板文件(表單中):
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
註意這裏是要在所有危險操作頁面的表單內都需要加入。
瀏覽器:F12 -> Network -> Disable Cache
// 整個文檔加載完畢後才會執行這個函數
$(function () {
$(‘#submit‘).click(function (event) {
// 阻止默認的表單提交行為
// event.preventDefault();
var email = $(‘input[name=email]‘).val();
var password = $(‘input[name=password]‘).val();
var csrftoken = $(‘input[name=csrf_token]‘).val();
// $.post() 方法用來提交表單
$.post({
‘url‘:‘/login/‘,
‘data‘:{
‘email‘: email,
‘password‘: password,
‘csrftoken‘: csrftoken
},
‘success‘:function (data) {
console.log(data);
},
‘fail‘:function (error) {
console.log(error);
}
});
})
});
5. Flask Restful
5.1 Restful API 介紹
Restful API
是用於在前端與後臺進行通信時使用的一套傳輸規範,這些規範可以使後臺開發變得更加輕松。
其采用的協議是 http
或 https
。
傳輸數據格式采用 json
而不是 xml
。使用 json
傳輸數據會變得更加簡單高效,而不是像 xml
那樣伴隨有眾多的固定代碼(類似於 html
的格式),即每次傳輸時 xml
占的資源更多。
並且其url 鏈接中,不能包含動詞,只能包含名詞;並且對於名詞,若出現復數,則必須加上 s
。
HTTP 的請求方法主要有以下 5
種,但實際上 get
和 post
就夠用了。
get
:獲取服務器上的一個資源post
:在服務器上創建一個紫愛雲put
:在服務器上更新資源(客戶端需要提交更新後的所有數據)patch
:在服務器上更新資源(客戶端只需要提交所更新的數據)delete
:在服務器上刪除一個資源
5.2 Flask-Restful 插件
安裝
Flask-Restful
需要在Flask 0.8
以上版本運行,在python 2.6
以上版本運行,通過pip install flask-restful
即可安裝。使用
使用之前必須從
flask_restful
中導入Api
和Resource
;然後用Api
將初始化的app
綁定起來;再定義一個類視圖,定義類視圖必須繼承自Resource
;最後用add_resource
方法將接口(URL
)與視圖綁定起來。完整代碼如下:from flask import Flask from flask_restful import Api,Resource # Api 用來綁定 app,Resource 用來創建類視圖 app = Flask(__name__) api = Api(app) class LoginView(Resource): def post(self): # 定義了什麽樣的方法,才能用什麽樣的請求 return {‘username‘:‘MYYD‘} # 可以直接返回字典類型的數據(因為字典數據已經自動轉換成Json格式了) api.add_resource(LoginView,‘/login/‘,endpoint=‘login‘) # 映射類視圖和接口,endpoint 用來指定 url_for 反轉到類視圖時的關鍵字 if __name__ == ‘__main__‘: app.run()
註意事項:
- 映射類視圖和接口時不指定
endpoint
,則進行url_for
反轉時默認使用視圖名稱的小寫,即上例中的loginview
。
add_resource
方法的第二個參數,用來指定訪問這個類視圖的接口,與之前不同的是,這個地方可以傳入多個接口。
- 映射類視圖和接口時不指定
5.3 Flask-Restful 參數驗證
基本使用
Flask-Restful
插件為我們提供了類似之前的WTForm
表單驗證的包,可以用來驗證提交的數據是否合法,叫做reqparse
。基本用法如下(3步驟):parser = reqparse.RequestParser() # 初始化一個 RequestParser 對象 parser.add_argument(‘password‘,type=int,help=‘password input error‘) # 指定驗證的參數名稱,類型以及驗證不通過時的提示信息 args = parser.parse_args() # 執行驗證
完整代碼如下:
from flask_restful import Api,Resource,reqparse class LoginView(Resource): def post(self): # post 方法提交數據時傳入的 username 和 password,這裏不需要定義 parser = reqparse.RequestParser() parser.add_argument(‘username‘,type=str,help=‘用戶名格式錯誤‘) # 如果提交數據時沒傳入,默認為 None parser.add_argument(‘age‘,type=int,help=‘密碼錯誤‘) args = parser.parse_args() print(args) return {‘username‘:‘MYYD‘}
add_argument
解析在使用
add_argument
對上傳的數據進行驗證時,可以根據需求使用不同的選項進行驗證,常用的選項有:default
:默認值,如果沒有傳入該參數,則使用default
為該參數指定默認的值。required
:置為True
時(默認為False
),該參數必須傳入值,否則拋出異常。type
:指定該參數的類型,並進行強制轉換,若強制轉換失敗則拋出異常。choices
:相當於枚舉類型,即該傳入的參數只能為choices
列表中指定的值。help
:當驗證失敗時拋出的異常信息。trim
:置為True
時對上傳的數據進行去空格處理(只去掉字符串前後的空格,不去掉字符串之間的空格)。
其中,
type
選項除了可以指定python
自帶的一些數據類型外,還可以指定flask_restful.inputs
下的一些特定類型來進行強制轉換。常用的類型如下:url
:會判斷上傳的這個參數是不是一個url
,若不是則拋出異常。regex
:會判斷上傳的這個參數是否符合正則表達式中的格式,若不符合則拋出異常。date
:將上傳的這個參數強制轉換成datetime.date
類型,若轉換不成功則拋出異常。
在使用
type
指定flask_restful.inputs
數據類型時的用法如下:parser.add_argument(‘birthday‘,type=inputs.date,help=‘日期輸入錯誤‘)
5.4 Flask-Restful 類視圖返回內容
返回數據時候可以使用最原始的方法,返回一個字典。但是 Restful
推薦我們使用 Restful
方法,如下:
- 先定義一個字典,該字典定義所有要返回的參數
- 再使用
marshal_with
(字典名) 傳入字典名稱 最後返回數據就行了,如下:
from flask_restful import Api,Resource,fields,marshal_with api = Api(app) class Article(object): def __init__(self,title,content): self.title = title self.content = content artilce = Article(‘MYYD‘,‘wuba luba dub dub‘) class LoginView(Resource): resource_field = { ‘title‘: fields.String, ‘content‘: fields.String } @marshal_with(resource_field) def get(self): return artilce # 可以直接返回 Article 的實例,會拿到 article 對象的兩個屬性並返回 api.add_resource(LoginView,‘/login/‘,endpoint=‘login‘)
這樣做的好處是:
- 可以少寫代碼
- 可以規範輸出,即如果
article
對象只有title
屬性而沒有content
屬性,也會返回content
的值,只不過該值被置為None
。
5.5 Flask-Restful 標準返回
5.5.1 復雜結構
對於一個類視圖,可以指定好一些數據字段用於返回。指定的這些數據字段,在此後使用 ORM
模型或者自定義模型時,會自動獲取模型中的相應字段,生成 Json
數據,並返回給客戶端。對於擁有子屬性的字段而言,若想成功獲取其屬性並返回給客戶端,需要引用 fields.Nested
並在其中定義子屬性的字段。整個例子如下:
模型關系
class User(db.Model): __tablename__ = ‘user‘ id = db.Column(db.Integer,primary_key=True) username = db.Column(db.String(50),nullable=False) email = db.Column(db.String(50),nullable=False) article_tag_table = db.Table( ‘article_tag‘, db.Column(‘article_id‘,db.Integer,db.ForeignKey("article.id"),primary_key=True), db.Column(‘tag_id‘,db.Integer,db.ForeignKey("tag.id"),primary_key=True) ) class Article(db.Model): __tablename__ = ‘article‘ id = db.Column(db.Integer,primary_key=True) title = db.Column(db.String(50),nullable=False) content = db.Column(db.Text) author_id = db.Column(db.Integer,db.ForeignKey(‘user.id‘)) author = db.relationship(‘User‘,backref=‘articles‘) tags = db.relationship(‘Tag‘,secondary=article_tag_table,backref=‘articles‘) class Tag(db.Model): __tablename__ = ‘tag‘ id = db.Column(db.Integer,primary_key=True) name = db.Column(db.String(50),nullable=False)
返回時定義的數據字段
註意這裏有三點必須實現:
- 導入相關包並初始化
app
- 定義返回數據的字段
- 使用裝飾器
marshal_with
傳入定義的數據字段
from flask_restful import Api,Resource,fields,marshal_with api = Api(app) class ArticleView(Resource): article_detail = { ‘article_title‘: fields.String(attribute=‘title‘), ‘content‘: fields.String, ‘author‘: fields.Nested({ # 返回有子屬性的字段時要用 fields.Nested() ‘username‘: fields.String, ‘email‘: fields.String, ‘age‘: fields.Integer(default=1) }), ‘tags‘: fields.Nested({ # 返回有子屬性的字段時要用 fields.Nested() ‘name‘: fields.String }) } @marshal_with(article_detail) def get(self,article_id): article = Article.query.filter_by(id=article_id).first() return article
- 導入相關包並初始化
5.5.2 重命名屬性
重命名屬性很簡單,就是返回的時候使用不同於模型本身的字段名稱,此操作需要借助 attribute
選項。如下所示代碼:
article_detail = {
‘article_title‘: fields.String(attribute=‘title‘)
}
Article
模型中的屬性原本是 title
,但是要返回的字段想要命名為 article_title
。如果不使用 attribute
選項,則在返回時會去 Article
模型中找 article_title
屬性,很明顯是找不到的,這樣以來要返回的 article_title
字段會被置為 Null
。使用 attribute
選項後,當返回 article_title
字段時,會去 Article
模型中找 attribute
選項指定的 title
屬性,這樣就可以成功返回了。
5.5.3 默認值
當要返回的字段沒有值時,會被置為 Null
,如果不想置為 Null
,則需要指定一個默認的值,此操作需要借助 default
選項。如下代碼所示:
article_detail = {
‘article_title‘: fields.String(attribute=‘title‘)
‘readed_number‘: fields.Integer(default=0)
}
當想要返回一篇文章的閱讀量時,若沒有從模型中獲取到該字段的值,若不使用 default
選項則該字段會被置為 Null
;若使用了該選項,則該字段會被置為 0
。
5.6 Flask-restful 細節
實際上,flask-restful
還可以嵌套在藍圖中使用,也能返回一個 html
模板文件。
嵌套藍圖使用
搭配藍圖使用時,在註冊
api
時就不需要使用app
了,而是使用藍圖的名稱,如下:article_bp = Blueprint(‘article‘,__name__,url_prefix=‘/article‘) api = Api(article_bp)
其他的和之前一樣,不過要在主 app 文件中註冊一下藍圖。
渲染模板
如果想使用
flask-restful
返回html
模板,則必須使用api.representation()
裝飾器來轉換返回數據的類型,並根據該裝飾器定義一個函數,用於返回該模板,如下:from flask import render_template,make_response @api.representation(‘text/html‘) def outPrintListForArticle(data,code,headers): # 這裏要傳入這三個參數 resp = make_response(data) # 其中,data 就是模板的 html 代碼 return resp class ListView(Resource): def get(self): return render_template(‘list.html‘) api.add_resource(ListView,‘/list/‘,endpoint=‘list‘)
Flask-論壇開發-4-知識點補充