flask-restful扩展
1.视图
1.1基本使用
from flask import Flask
from flask_restful import Api, Resource, output_json
import json
# json.dumps("data", ensure_ascii=False)
# 1.创建app对象
app = Flask(__name__)
# 不允许将字典中的中文编码成ascii码
# Flask-Restful中的中文编码成ascii码
app.config["RESTFUL_JSON"] = {
"ensure_ascii": False}
# Flask不允许中文编码
# app.config["JSON_AS_ASCII"] = False
# /user/
# 获取服务器资源:GET
# 新建服务器资源:POST
# 删除服务器资源: DELETE
# 传输大量数据给服务器:PUT
# 局部更新: PATCH
# 请求参数:组织成json格式
# 响应数据: 以json格式返回
# 响应状态码应用以HTTTP标准状态码返回 201 401 403 404 405
# 2.将app对象包装成具备有restful风格的api对象
# 参数类型:app对象或者蓝图对象
api = Api(app)
# 3.自定义类视图 继承:Resource
class DemoResource(Resource):
def get(self):
# 返回字典,最终底层会将字典转换成json字符串
return {
"get": "可以显示中文吗?"}
def post(self):
return {
"post": "post body"}
# 4.给类视图添加路由信息
api.add_resource(DemoResource, '/')
# api.add_resource(DemoResource, '/', endpoint="类视图的别名")
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(debug=True, port=8000)
1.2视图装饰器
from flask import Flask
from flask_restful import Api, Resource
app = Flask(__name__)
# 1.创建api对象
api = Api(app)
def mydecorator1(func):
def wrapper(*args, **kwargs):
print("mydecorator1 dispatch")
return func(*args, **kwargs)
return wrapper
def mydecorator2(func):
def wrapper(*args, **kwargs):
print("mydecorator2 dispatch")
return func(*args, **kwargs)
return wrapper
# 需求:给类视图添加装饰器
# 2.自定义类视图
class DemoResource(Resource):
# 方案1:给类视图中所有方法都添加上装饰器
# method_decorators = [mydecorator1, mydecorator2]
# 方案2:给类视图中指定方法添加指定的装饰器
method_decorators = {
"get": [mydecorator1, mydecorator2],
"put": [mydecorator1]
}
def get(self):
return {
"foo": "get message"}
def put(self):
return {
"put": "put message"}
# 3.添加路由信息
api.add_resource(DemoResource, '/index')
if __name__ == '__main__':
app.run(debug=True, port=8000)
2.请求
from flask_restful import Api, Resource, output_json
from flask_restful.reqparse import RequestParser
# flask-restful自带的参数类型
from flask_restful.inputs import *
import re
app = Flask(__name__)
api = Api(app)
def get_userid(value):
# user:1
if re.match(r'^user:', value):
# 截取id返回
return value[5:]
else:
raise ValueError("invalid value")
class DemoResource(Resource):
def get(self):
# 1.创建解析对象
parser = RequestParser()
# 2.添加解析参数和解析规则
# 默认会去get请求的查询字符串中提取参数
# required=True 必传参数
# location='json' 提取参数的位置 参数值为字符串 args form json files cookies headers
# default=18 设置默认值
parser.add_argument("name", required=True, location='json')
parser.add_argument("age", default=18, location='json')
# 参数类型 type
# 1.python自带类型:type=int
# parser.add_argument("number", required=True, location='json', type=int)
# parser.add_argument("number", required=True, location='json', type=str)
# 2.flask-restful自带的类型:date日期 regex正则表达式 int_range指定数据范围
# 2020-09-20 00:00:00
# <class 'datetime.datetime'>
# 将时间字符串转换成datetime日期格式
# parser.add_argument("number", required=True, location='json', type=date)
# "Invalid argument: 300 超出限定范围就会报错
# parser.add_argument("height", required=True, location='json', type=int_range(130, 250))
# regex正则表达式 手机号码格式
# parser.add_argument("number", required=True, location='json', type=regex(r'^1[3-9]\d{9}$'))
# bool类型
# parser.add_argument("number", required=True, location='json', type=boolean)
# 3.自定义数据类型-自定函数
parser.add_argument("number", required=True, location='json', type=get_userid)
# 3.开启解析,获取解析结果
ret = parser.parse_args()
# 4.获取参数
name = ret.name
age = ret["age"]
number = ret.number
print(name)
print(age)
print(number)
print(type(number))
return {
"get": "message"}
3.响应
3.1序列化
from flask_restful import Api, Resource, fields, marshal, marshal_with, output_json
app = Flask(__name__)
# 1.将app对象包装创建api对象 [用于管理类视图(资源)]
api = Api(app)
class User(object):
def __init__(self):
self.name = "curry"
self.age = 18
self.height = 180.8
self.mylist = [30, 24]
self.mydict = {
"gender": True
}
def to_dict(self):
my_dict = {
"name": self.name,
"age": self.age,
"my_list": self.mylist,
"my_dict": self.mydict
}
return my_dict
# 1.定义序列化规则字典
marshal_dict = {
"name": fields.String(),
"age": fields.Integer(default=18),
"height": fields.Float(),
"mylist": fields.List(fields.Integer),
"mydict": fields.Nested({
"gender": fields.Boolean})
}
# 2.使用marshal函数进行序列化
# 2.定义类视图 继承Resource
class DemoResource(Resource):
method_decorators = {
"post": [marshal_with(marshal_dict)]
}
def get(self):
# 类视图响应的content-type默认变为json形式
# 类视图的返回值可以是字典, 会被自动转为json字符串
# 序列化方案1:
# 创建用户对象
user = User()
# 利用marshal函数将用户对象序列化成字典
return marshal(user, marshal_dict)
# 序列化方案2:marshal_with装饰器
# @marshal_with(marshal_dict)
def post(self):
# 加上了marshal_with装饰器,返回的user对象先经过装饰器序列化成字典,然后在返回
user = User()
return user
# 序列化方案3:[推荐]
def put(self):
# 创建用户对象
user = User()
return user.to_dict()
# 3.api对象给类视图添加路由
api.add_resource(DemoResource, '/')
3.2自定义json
"""
需求:自定义json字符串的返回格式
原始json字符串数据:
{
"username": "james",
"number": 23
}
自定义返回的json字符串的格式:
{
"message": "OK or ERROR",
"data": {
"username": "james",
"number": 23
}
}
方案1:修改源码 【不推荐】
方案2:复制源代码,使用装饰器api.representation()拦截output_json处理字典的方法,自己调整json格式
from flask import make_response, current_app
from flask_restful.utils import PY3
from json import dumps
# mediatype='application/json' 指明返回参数为json字符串类型
# @api.representation 拦截返回的字典数据
# @api.representation(mediatype='application/json')
def output_json(data, code, headers=None):
# Makes a Flask response with a JSON encoded body
settings = current_app.config.get('RESTFUL_JSON', {})
if "message" not in data:
data = {
"message": "OK",
"data": data
}
if current_app.debug:
settings.setdefault('indent', 4)
settings.setdefault('sort_keys', not PY3)
# always end the json dumps with a new line
# see https://github.com/mitsuhiko/flask/pull/1262
dumped = dumps(data, **settings) + "\n"
resp = make_response(dumped, code)
resp.headers.extend(headers or {})
return resp
"""
# 方案2:自定义返回的json格式
# 装饰器调用
api.representation(mediatype="application/json")(output_json)
# 2.定义类视图 继承Resource
class DemoResource(Resource):
def get(self):
# 类视图响应的content-type默认变为json形式
# 类视图的返回值可以是字典, 会被自动转为json字符串
return {
'username': 'james', 'number': 23}
def post(self):
return {
'foo': 'post'}