文章目錄
一、flask-restful
在django中
django restful(是一種api接口的設計規範,通常路由的編寫不會出現動詞)
get 請求 getuserinfo 獲取到所有用戶的所有信息
getuserinfo id 獲取指定id用戶的所有信息
getuserinfo name 獲取執行用戶名字的信息
getuserinfo age 獲取指定年齡的用戶信息
getuserinfo age name 獲取年齡爲xxx 名字爲 xxx 的用戶的信息
userinfo
增加用戶的操作: def adduserinfo add_userinfo
獲取用戶信息: def get_userinfo get_userinfo
restful中 class userinfo:
def get:
獲取數據
def post:
添加數據
def put:
修改數據
def delete:
刪除數據
1. flask 中restful安裝及配置,基本結構(路由的兩種寫法)
① 第一步:安裝
安裝插件:flask-restful
pip install flask-restful
相關安裝包
② restful使用(配置,收集路由)
- main.py restful 配置信息
③ 基本結構(路由的兩種寫法)
from main import api
from flask_restful import Resource
## main.py中
api = Api(app) ## 負責收集路由 收集類視圖的註冊信息
- from flask_restful import Resource 中Resource的介紹
- from main import api 實例化api對象調用方法的介紹
- restful基本結構
2. 視圖中使用restful
① get請求
- get請求初步封裝
#-------------------------------restful-----------------------------
from main import api
from flask_restful import Resource
## 路由的寫法(收集路由,收集類視圖)Api 標明接口 v1版本 leave對leave的操作
@api.resource("/Api/v1/leave/")
class LeaveApi(Resource):
def get(self):
"""
處理get請求
獲取資源
:return:
"""
result_data = {}
data = request.args
id = data.get("id")
# request_name = data.get("request_name")
if id:
leave = Leave.query.get(int(id))
if leave is not None:
result_data = {
"request_id":leave.request_id,
"request_name":leave.request_name,
"request_type":leave.request_type,
"request_end":str(leave.request_end),
"request_description":leave.request_description,
"request_start":str(leave.request_start),
"request_phone":leave.request_phone,
"request_status":leave.request_status,
}
else:
leaves = Leave.query.all() ## 使用數據
result_data = []
for leave in leaves:
info = {
"request_id": leave.request_id,
"request_name": leave.request_name,
"request_type": leave.request_type,
"request_end": str(leave.request_end),
"request_description": leave.request_description,
"request_start": str(leave.request_start),
"request_phone": leave.request_phone,
"request_status": leave.request_status,
}
result_data.append(info)
return result_data
- 效果演示
- 不傳參獲取所有數據
- 傳入指定id查詢指定數據
- 傳入指定字段屬性值進行查詢
② post請求
- post請求函數
def post(self):
"""
處理post請求
:return:
"""
data = request.form
return "post請求%s" %data
- 效果演示
③ put請求
- put請求函數
def put(self):
"""
處理put請求
:return:
"""
data = request.form
return "put請求%s" % data
- 結果演示
④ delete請求
- delete請求函數
def delete(self):
"""
處理delete請求
:return:
"""
data = request.form
return "delete請求%s" % data
⑤ Django和flask中一些方法不同的獲取方式
在Django中 put和delete傳遞的參數放在下面的文本中,
用request.body獲取值
在flask中 put和 delete 傳遞的參數和post一樣放在下面的文本框中,
用request.form.get獲取值
3. 代碼優化
① 規定返回格式,將其寫在init初始化文件中
- 提取封裝公共的返回結構
- 返回selt.result
② 封裝get中冗餘的代碼
- get請求中代碼冗餘,將公共的地方封裝
- 將數據結果封裝成函數,方便調用
③ 封裝get請求
- get請求封裝 實現查詢功能
from main import api
from flask_restful import Resource
## 路由的寫法(收集路由,收集類視圖)Api 標明接口 v1版本 leave對leave的操作
@api.resource("/Api/v1/leave/")
class LeaveApi(Resource):
def __init__(self):
super(LeaveApi, self).__init__()
self.result = {
"method": "get",
"version": "v1",
"data": ""
}
def create_data(self,leave):
"""
定義返回的數據
:return:
"""
result_data = {
"request_id": leave.request_id,
"request_name": leave.request_name,
"request_type": leave.request_type,
"request_end": str(leave.request_end),
"request_description": leave.request_description,
"request_start": str(leave.request_start),
"request_phone": leave.request_phone,
"request_status": leave.request_status,
}
return result_data
def get(self):
"""
處理get請求
獲取資源
:return:
"""
result_data = {}
data = request.args
id = data.get("id")
# request_name = data.get("request_name")
if id:
leave = Leave.query.get(int(id))
if leave is not None:
result_data = self.create_data(leave)
else:
leaves = Leave.query.all() ## 使用數據
result_data = []
for leave in leaves:
info = self.create_data(leave)
result_data.append(info)
self.result["data"] = result_data
# result = {
# "method":"get",
# "version":"v1",
# "data":result_data
# }
return jsonify(self.result)
- 結果演示:
④ post請求封裝
- post請求實現增加功能
def post(self):
"""
處理post請求 增加數據的功能
:return:
"""
data = request.form
leave = Leave()
leave.request_id = data.get("request_id")
leave.request_name = data.get("request_name")
leave.request_type = data.get("request_type")
# end = str(data.get("request_end"))
end = data.get("request_end")
request_end = datetime.date(*map(int,end.split('-')))
# leave.request_end = data.get("request_end")
leave.request_end = request_end
leave.request_description = data.get("request_description")
# start = str(data.get("request_start"))
start = data.get("request_start")
# request_start = datetime.date(*map(int,start.split('-')))
# leave.request_start = data.get("request_start")
leave.request_start = datetime.date(*map(int,start.split('-')))
leave.request_phone = data.get("request_phone")
leave.request_status = data.get("request_status")
leave.save()
self.result["method"] = "post"
self.result["data"] = self.create_data(leave)
return jsonify(self.result)
⑤ 封裝put請求
- put請求實現更新功能
def put(self):
"""
處理put請求 更新數據
可以支持更改部分數據
根據id查詢對象 ----》 id
修改的是 對象裏面的屬性
對象屬性 ----》 setattr
:return:
"""
data = request.form
id = data.get("id") ## 假條id
leave = Leave.query.get(id) ## 找到被修改的數據 leave是一個對象
for key,value in data.items():
if key!= "id":
if hasattr(leave,key):
if key == "request_start" or key == "request_end":
value = datetime.date(*map(int,value.split('-')))
setattr(leave, key, value)
setattr(leave,key,value)
leave.merge()
self.result["method"] = "put"
self.result["data"] = self.create_data(leave)
return jsonify(self.result)
⑥ 封裝delete請求
- delete請求實現刪除功能
def delete(self):
"""
處理delete請求
:return:
"""
data = request.form
id = data.get("id")
leave = Leave.query.get(id)
leave.delete()
self.result["method"] = "delete"
self.result["data"] = self.create_data(leave)
return jsonify(self.result)
- 效果演示
4. 接口提供數據實現前後端分離
① 接口(api)介紹
- api接口提供數據的支持,將前端html和後端進行分離
- 返回的數據通常是json
- restful 風格的接口,命名不出現動詞
- 接口開發的目的,增加數據的可用性,
- 前端(pc,app, 小程序,爬蟲,)
寫web頁面,請求api接口獲取數據,前端web現在ajax,vue
② 前後端分離demo
-
視圖: (有兩個函數)
- 提供返回頁面的功能
- 提供返回數據的api接口
-
模板
{% extends "base.html" %}
{% block title %}
api demo
{% endblock %}
{% block label %}
api demo
{% endblock %}
{% block content %}
{% endblock%}
{% block script %}
<script src="/static/vendor/jquery/jquery.min.js"></script>
<script>
$.ajax({
url:"/Api/v1/leave/",
type:"get",
data:"",
success:function (data) {
console.log(data)
// 返回的數據可以通過列表在此頁面展示給用戶
},
error:function (error) {
console.log(error)
}
})
</script>
{% endblock %}
- 通過列表套字典的方式將數據傳遞給前端html模板
可以參照Django的前後端數據分離
二、Flask-migrate
1. flask-migrate的介紹
migrate是flask對數據模型的管理插件
在實際的開發環境中,經常會發生數據庫修改的行爲。一般我們修改數據庫不會直接手動的去修改,而是去修改ORM對應的模型,然後再把模型映射到數據庫中。這時候如果有一個工具能專門做這種事情,就顯得非常有用了,而flask-migrate就是做這個事情的。flask-migrate是基於Alembic進行的一個封裝,並集成到Flask中,而所有的遷移操作其實都是Alembic做的,他能跟蹤模型的變化,並將變化映射到數據庫中。
可通過Flask命令行界面或Flask-Script擴展名使用數據庫操作。
官方文檔:Flask-migrate
2. 使用flask-migrate原因
不同步更新問題
因爲採用db.create_all在後期修改字段的時候,不會自動更改到數據庫中,必須刪除表,然後重新運行db.create_all纔會重新映射,這樣是不符合實際情況的。
因此flask-migrate就解決了這個問題,可以直接將修改的東西映射到數據庫中。
3. 安裝及使用介紹
pip install flask-migrate
migrate 插件通常不單獨使用,需要結合flask的script插件進行使用。
能夠解決 create_all 不足的問題:
解決migrate不同步更新表結構
4. 使用前的配置
-
配置main.py
-
使用migrate綁定app和db
migrate = Migrate(app,db)
-
配置manage.py
-
讓python支持命令行工作
manager= Manager(app)
-
添加遷移腳本的命令到manager中
manager.add_command("db",MigrateCommand)
-
最後的代碼
5. flask-migrate相關命令
- 初始化一個遷移腳本的環境,只需要執行一次
python manage.py db init
- 將模型生成遷移文件,只要模型更改了,就需要執行一次這個命令
python manage.py db migrate
- 將遷移文件真正的映射到數據庫中。每次也需要執行一次這個命令
python manage.py db upgrade
- 回退操作
python manage.py downgrade
- 查看版本記錄
python manage.py db history
6. 執行數據遷移操作步驟
- 遷移前初始化,生成遷移文件目錄
python manage.py db init
- 生成遷移文件版本記錄version
python manage.py db migrate
- 生成新版本,版本升級
python manage.py db upgrade
- 查看版本記錄
python manage.py db history
三、flask中的CSRF
flask_wtf 的form表單類,csrf_token會隨着form表單生成,但是不校驗
flask-wtf自動生成csrf隱藏域
1. CSRF校驗
使用:
- 開啓csrf校驗
- main.py中導入CSRFProtect csrf保護
- 效果:
2. 前端頁面使用csrf
通過實驗,最終找到使用方法
結論:form表單加隱藏域即可通過驗證
3. 在測試的時候遇到CSRF解決辦法
在測試的時候
- post、put、delete等可以加一個csrf_token鍵,
- 然後找個網頁找個csrf_token值
- 將值複製進去
- 驗證結果
4. 避免CSRF
- 實例化csrf保護
- 給要避免csrf的函數加裝飾器
四、給類視圖增加多個裝飾器
1.method_decorators介紹
method_decorators 類屬性,Resource會檢測method_decorators類屬性當中有沒有給下面的方法增加裝飾器
method_decorators 會給方法增加裝飾器
method_decorators = [] 代表將該類中的所有方法都增加裝飾器
2. 給類視圖加多個裝飾器
- 代碼
### 類視圖裝飾器
def func1(func):
def inner():
print("func1裝飾器")
func()
return inner
def func2(func):
def inner():
print("func2裝飾器")
func()
return inner
class Demo(Resource):
method_decorators = [func1,func2]
def get(self):
"""
:return:
"""
return "get請求"
def post(self):
"""
:return:
"""
return "post 請求"
api.add_resource(Demo,"/Demo/") ##
## 裝飾器相當於
@func2
@func1
def get():
pass
- get請求結果
- post請求結果
順序,列表中先去遍歷,func1先裝飾,再在外面裝飾func2
3. 給指定的方法裝飾指定的裝飾器
- get請求
- post請求
4. 給一個方法加多個裝飾器
- 在restful中只給get方法加登錄裝飾器