平时在写接口的时候,我们通常会在视图函数中去判断时候有某一个参数,并转换参数类型,这时候会使得视图函数变得非常的笨重,可读性差,使用flask_apispec可以解决这一个问题。
pip install flask-apispec
from flask import Flask, jsonify
from flask_apispec import use_kwargs, marshal_with
from marshmallow import fields
app = Flask(__name__)
@app.route('/test')
@use_kwargs({'email': fields.Str(), 'is_able': fields.Boolean()})
def test(**kwargs):
# 从request的 args、form、get_json()中拿到user_kwargs装饰器内存在的key
# 将获取的key,value放在kwargs参数中去
print(kwargs)
return json({'msg': 'test'})
from flask import Flask
from flask_apispec import use_kwargs, marshal_with
from marshmallow import fields, Schema
from .models import Pet
app = Flask(__name__)
class PetSchema(Schema):
class Meta:
# 指定响应模型的数据字段
fields = ('name', 'category', 'size')
@app.route('/pets')
@use_kwargs({'category': fields.Str(), 'size': fields.Str()}) # 获取参数到,传到kwargs中去
@marshal_with(PetSchema(many=True)) # many表示可以返回多个Pet,放在一个列表里
# @marshal_with(PetSchema) # 这样只返回一个数据
def get_pets(**kwargs):
# 直接返回,不需要再去序列化,当时好像里面不能再加一些像msg这样的数据进去
return Pet.query.filter_by(**kwargs)
def use_kwargs(args, locations=None, inherit=None, apply=None, **kwargs):
pass
它的实现是使用了webargs的FlaskParser类,来帮助我们获取全局request对象的参数
默认的locations有三个 DEFAULT_LOCATIONS = ("querystring", "form", "json")
locations可以为一个元祖,官方是这么说的
tuple locations: Where on the request to search for values.Can include one or more of
``('json', 'querystring', 'form','headers', 'cookies', 'files')``.
所以说我们可以选用('json', 'querystring', 'form','headers', 'cookies', 'files')
作为locations的值
如果我们直接使用use_kwargs时不指定locations参数,还可能会出现一些问题,比如我们想在json中获取的参数,结果querystring中也有而json中没有,这样会拿到querystring的参数,错误的拿到参数
import re
from marshmallow import fields
from flask_apispec import use_kwargs
from flask_restful import Resource
def valid_phone(phone):
phone_rule = "^((13[0-9])|(14[5,7])|(15[0-3,5-9])|(17[0,3,5-8])|(18[0-9])|166|198|199|(147))\\d{8}$"
return True if re.match(phone_rule, phone) else False
class TestResource(Resource):
@use_kwargs({
"phone": fields.String(required=True, validate=valid_phone),
"phone_code": fields.String(required=True, validate=lambda phone_code: True if len(phone_code) == 6 else False)
}, locations=("json", ))
def post(self, **kwargs):
phone = kwargs.get("phone")
phone_code = kwargs.get("phone_code")
# ...
上面的use_kwargs方法指定了locations=("json", )
这样就不会从其他的位置去获取参数了,还有使用marshmallow.fields
时,可以使用validate来对参数进行合法性的校验,这样能使得我们的代码看的非常的工整,只用专心去实现逻辑部门的内容。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>422 Unprocessable Entity</title>
<h1>Unprocessable Entity</h1>
<p>The request was well-formed but was unable to be followed due to semantic errors.</p>
如果前端传来的参数不合法,会出现422的情况,这时候不要着急,核对一下参数类型是否合法,或者后台校验是否有问题