Flask_restful拓展
@目录@一:视图:1:基本使用1.1:安装 flask-restful:1.2: 构建RESTAPI1.3:flask_restful返回时中文编码问题:2:类视图装饰器3:蓝图和类视图二:请求:三:响应:1:序列化2:自定义JSON一:视图:1:基本使用1.1:安装 flask-restful:pip install flask-restful1.2: 构建RESTAPI1:创建app对象。2:
·
@目录@
一:视图:
1:基本使用
1.1:安装 flask-restful:
pip install flask-restful
1.2: 构建RESTAPI
- 1:创建app对象。
- 2:将app对象包装成具备restful风格的组件对象。
- 3:定义类视图继承于Resourse。
- 4:给视图添加路由信息。
- 注意点:当返回一个字典时,flask_restful会自动封装成json。
- 类视图响应的 content-type 默认变为 JSON形式
- endpoint表示起别名:给这个视图起一个别名。
from flask import Flask
from flask_restful import Api, Resource
# 1: 创建app对象
app = Flask(__name__)
# 2:将app对象包装成具备restful风格的组件对象api
api = Api(app)
# 3:定义类视图继承于:Resourse
class DemoResourse(Resource):
def get(self):
return {'get': "get_message"}
def post(self):
return {'post': "post_message"}
# 4:给视图添加路由信息
api.add_resource(DemoResourse, '/',endpoint= "myresource")
@app.route('/login')
def login():
print(app.url_map)
return ""
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000, debug=True)
原来是类名的小写,现在改成自己定义的这个名字了。
1.3:flask_restful返回时中文编码问题:
- 在flask_restful中,output_json控制返回的格式:
- app.config[‘RESTFUL_JSON’] = {“ensure_ascii”: False} 解决中文编码问题。
源码解析:
根据流程,发现就是字典中,没有取消转换ASCII的配置。
解决方案:
增加配置项:
# 配置转换成中文
app.config['RESTFUL_JSON'] = {"ensure_ascii": False}
2:类视图装饰器
- 方案一:method_decorators列表的形式。
- 方案二:method_decorators字典的形式。
- 注意:装饰器装饰的顺序和执行的顺序,装饰的顺序是,先装饰列表前面的,再装饰后面的,执行顺序是先执行后面的,再执行前面的。
<案例一>使用列表装饰,并且查看装饰器的执行过程。
from flask import Flask
from flask_restful import Api, Resource
"""
# 需求:类视图添加装饰器
"""
app = Flask(__name__)
api = Api(app)
# 装饰器一
def mydecorator(func):
print("第一个装饰器装饰了")
def wrapper(*args, **kwargs):
print("mydecorator dispatch")
return func(*args, **kwargs)
return wrapper
# 装饰器二:
def mydecorator2(func):
print("第二个装饰器也装饰了")
def wrapper(*args, **kwargs):
print("mydecorator2 dispatch")
return func(*args, **kwargs)
return wrapper
class DemoResource(Resource):
# 方案一:给类视图的所有方法添加装饰器
method_decorators = [mydecorator, mydecorator2]
def get(self):
return {"get": "get message"}
def post(self):
return {"post": "post body"}
api.add_resource(DemoResource, '/')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000, debug=True)
执行效果来看:
<案例二>: 给指定添加装饰器:
分析源码:
分析源码得到,我们也可以将method_decorators赋值成一个字典,键是请求方式,值是个列表,列表里面是多个视图。
因此也可以这样进行装饰。
class DemoResource(Resource):
# 方案一:给类视图的所有方法添加装饰器
# method_decorators = [mydecorator, mydecorator2]
method_decorators = {
'get': [mydecorator, mydecorator2],
'post': [mydecorator]
}
def get(self):
return {"get": "get message"}
def post(self):
return {"post": "post body"}
3:蓝图和类视图
- 创建蓝图对象:user_dp = Blueprint(“user”, name, url_prefix="/user")
- 将蓝图对象包装成api对象: api = Api(user_dp)
- 给蓝图对象添加路由信息: api.add_resource(DemoResource, ‘/info’)
- 注册蓝图: app.register_blueprint(user_dp)
1: 主函数代码:
from user import user_dp
from flask import Flask, make_response, Response, request
app = Flask(__name__)
# 4: 注册蓝图
app.register_blueprint(user_dp)
if __name__ == '__main__':
print(app.url_map)
app.run(host='0.0.0.0', port=8000, debug=True)
2:__init__初始化文件:
from flask import Blueprint
from flask_restful import Api
# 1:创建蓝图对象
user_dp = Blueprint("user", __name__, url_prefix="/user")
# 2: 将蓝图对象包装成api对象
api = Api(user_dp)
# 3:给蓝图对象添加路由信息
from .views import DemoResource
api.add_resource(DemoResource, '/info')
3:视图文件:
from flask_restful import Resource
class DemoResource(Resource):
def get(self):
return "Demo"
二:请求:
1:请求的基本使用:
- 1: 创建解析对象: parser = RequestParser()
- 2: 添加解析参数和规则: parser.add_argument(“name”, required=True, location=“json”)
- 3:开始解析获取解析结果: ret = parser.parse_args()
- 4:从解析结果中获取值: name = ret.name 或者 age = ret[‘age’]
from flask import Flask
from flask_restful import Api, Resource
from flask_restful.reqparse import RequestParser
app = Flask(__name__)
api = Api(app)
class DemoResource(Resource):
def get(self):
# 1: 创建解析对象
parser = RequestParser()
# 2: 添加解析参数和规则:location指的是前端传递的格式:json, args, text, form, files
parser.add_argument("name", required=True, location="json")
parser.add_argument("age", required=18, location="json")
# 3:开始解析,获取解析结果
ret = parser.parse_args()
# 4: 从解析结果中提取参数值
name = ret.name
age = ret['age']
print(name)
print(age)
return {"foo": "get"}
def post(self):
return {"foo": "post"}
api.add_resource(DemoResource, '/')
if __name__ == '__main__':
print(app.url_map)
app.run(host='0.0.0.0', port=8000, debug=True)
2:type的三中类型:
- 1: python自带的类型
- 2:flask_restful自己内置的
- 3:自己定义的函数/类。
# python自带的类型:
parser.add_argument("name", required=True, location="json", type= str)
parser.add_argument("age", required=True, location="json", type= int)
#flask_restful自带的类型:
parser.add_argument("age", required=True, location="json", type=int_range(0, 100))
parser.add_argument("gender", required=True, location="json", type=boolean)
parser.add_argument("birthday", required=True, location="json", type=date)
parser.add_argument("mobile", required=True, location="json", type=regex(r'^1[3-9]\d{9}$'))
# 类的外部定义一个函数:
def get_user(value):
if re.match(r'^user', value):
return value[5:]
else:
raise ValueError("invalid user")
# 自定义的函数/类
parser.add_argument("user", required=True, location="json", type=get_user)
三:响应:
1:序列化
<方案一>:自定义一个类,然后自定义序列化规则,然后创建类的对象,最后将对象和规则传入marshal函数中。
from flask import Flask
from flask_restful import Api, Resource, marshal,marshal_with, fields
# marshal是序列化函数,marshal_with是装饰器。
# 序列化字段模块fields
# 需求,将模型类对象转换成字典,flask_restful内部的output_json会转换成字符串。
app = Flask(__name__)
api = Api(app)
class Person(object):
def __init__(self):
self.name = "curry"
self.age = 18
self.height = 185.6
self.mylist = [30, 20, 50]
self.mydict = {
"gender": True
}
user_dict = {
"name": fields.String,
"age": fields.Integer(default=28),
"height": fields.Float,
"mylist": fields.List(fields.Integer),
"mydict": {"gender": fields.Boolean}
}
class DemoResource(Resource):
def get(self):
# 1: 创建一个对象
user = Person()
# 2:使用marshal函数,传入被序列化对象和序列化规则
return marshal(user, user_dict)
def post(self):
return {"foo": "post"}
api.add_resource(DemoResource, '/')
if __name__ == '__main__':
print(app.url_map)
app.run(host="0.0.0.0", port=8000,debug=True)
<方案二>: 使用marshal_with装饰器:
method_decorators = {
"post": [marshal_with(user_dict)]
}
from flask import Flask
from flask_restful import Api, Resource, marshal,marshal_with, fields
# marshal是序列化函数,marshal_with是装饰器。
# 序列化字段模块fields
# 需求,将模型类对象转换成字典,flask_restful内部的output_json会转换成字符串。
app = Flask(__name__)
api = Api(app)
class Person(object):
def __init__(self):
self.name = "curry"
self.age = 18
self.height = 185.6
self.mylist = [30, 20, 50]
self.mydict = {
"gender": True
}
user_dict = {
"name": fields.String,
"age": fields.Integer(default=28),
"height": fields.Float,
"mylist": fields.List(fields.Integer),
"mydict": {"gender": fields.Boolean}
}
class DemoResource(Resource):
method_decorators = {
"post": [marshal_with(user_dict)]
}
def get(self):
# 1: 创建一个对象
user = Person()
# 2:使用marshal函数,传入被序列化对象和序列化规则
return marshal(user, user_dict)
def post(self):
user = Person()
return user
api.add_resource(DemoResource, '/')
if __name__ == '__main__':
print(app.url_map)
app.run(host="0.0.0.0", port=8000,debug=True)
<方案三>:自己转换(推荐)
from flask import Flask
from flask_restful import Api, Resource, marshal,marshal_with, fields
# marshal是序列化函数,marshal_with是装饰器。
# 序列化字段模块fields
# 需求,将模型类对象转换成字典,flask_restful内部的output_json会转换成字符串。
app = Flask(__name__)
api = Api(app)
class Person(object):
def __init__(self):
self.name = "curry"
self.age = 18
self.height = 185.6
self.mylist = [30, 20, 50]
self.mydict = {
"gender": True
}
def to_dict(self):
my_dict = {
"name": self.name,
"age": self.age,
"height": self.height,
"mylist": self.mylist,
"mydict": self.mydict
}
return my_dict
user_dict = {
"name": fields.String,
"age": fields.Integer(default=28),
"height": fields.Float,
"mylist": fields.List(fields.Integer),
"mydict": {"gender": fields.Boolean}
}
class DemoResource(Resource):
def get(self):
# 1: 创建一个对象
user = Person()
# 2:将对象转化成字典返回
return user.to_dict()
api.add_resource(DemoResource, '/')
if __name__ == '__main__':
print(app.url_map)
app.run(host="0.0.0.0", port=8000,debug=True)
2:自定义JSON
方案一:自定义output_json,然后使用语法糖进行装饰。@api.representation(‘application/json’)。
from flask import Flask, current_app, make_response
from flask_restful import Api, Resource, output_json
from flask import make_response, current_app
from flask_restful.utils import PY3
from json import dumps
app = Flask(__name__)
api = Api(app)
"""
需求:修改JSON的返回个格式
解决方案:使用装饰器拦截output_json底层源代码,定义json格式。
"""
@api.representation('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 "messgae" not in data:
data = {
"message": "ok",
"data": data
}
if current_app.debug:
settings.setdefault('indent', 4)
settings.setdefault('sort_keys', not PY3)
dumped = dumps(data, **settings) + "\n"
resp = make_response(dumped, code)
resp.headers.extend(headers or {})
return resp
class DemoResource(Resource):
def get(self):
return {"foo": "get"}
def post(self):
return {"foo": "post"}
api.add_resource(DemoResource, '/')
if __name__ == '__main__':
print(app.url_map)
app.run(host="0.0.0.0",debug=True, port=8000)
<方案二>:将代码封装起来,然后使用装饰器进行主动装饰。
新建utils.py
from flask import make_response, current_app
from flask_restful.utils import PY3
from json import dumps
def output_json(data, code, headers=None):
"""Makes a Flask response with a JSON encoded body"""
settings = current_app.config.get('RESTFUL_JSON', {})
if "messgae" not in data:
data = {
"message": "ok",
"data": data
}
if current_app.debug:
settings.setdefault('indent', 4)
settings.setdefault('sort_keys', not PY3)
dumped = dumps(data, **settings) + "\n"
resp = make_response(dumped, code)
resp.headers.extend(headers or {})
return resp
在主要main.py中主动装饰:
# 方案二:装饰器主动装饰
api.representation(mediatype="application/json")(output_json)
更多推荐
已为社区贡献3条内容
所有评论(0)