Flask框架_02—Flask-RESTful

本文详细介绍了如何使用Flask-RESTful创建REST API,包括HelloWorld示例、视图命名、蓝图应用、装饰器使用、参数解析和响应处理。同时探讨了如何定制返回的JSON格式,以满足统一的结构需求。
摘要由CSDN通过智能技术生成

目录

起步

1 安装

2 Hello World

关于视图

1 为路由起名

2 蓝图中使用

3 装饰器

6.3 关于请求处理

实列:

参数说明

1 required

2 help

3 action

4 type

5 location

6.4 关于响应处理

1 序列化数据

2 定制返回的JSON格式

需求

解决


起步

Flask-RESTful是用于快速构建REST API的Flask扩展。

1 安装

pip install flask-restful

2 Hello World

# 创建Api类对象   收集类视图的注册信息  在flask类代表不同的资源  不同的方法对应到不同的请求方式

api对象收集路径信息跟路由绑定的

from flask import Flask
from flask_restful import Resource, Api

app = Flask(__name__)
api = Api(app)

class HelloWorldResource(Resource):
    def get(self):
        return {'hello': 'world'}

    def post(self):
        return {'msg': 'post hello world'}

api.add_resource(HelloWorldResource, '/')

# 此处启动对于1.0之后的Flask可有可无
if __name__ == '__main__':
    app.run(debug=True)

注:flask_restful中返回的字典类型 可以自动转化为json

关于视图

1 为路由起名

通过endpoint参数为路由起别名

api.add_resource(HelloWorldResource, '/', endpoint='HelloWorld')

2 蓝图中使用

from flask import  Flask,Blueprint
from flask_restful import Resource,Api
app=Flask(__name__)

# 1 创建蓝图对象
bp=Blueprint("bp",__name__)

# 创建Api类对象   收集类视图的注册信息  在flask类代表不同的资源  不同的方法对应到不同的请求方式
# api=Api(app)
# 2.创建Api扩展的对象时 绑定蓝图对象
api=Api(bp)

class HelloWorldResource(Resource):
    def get(self):
        return {"hello":"world"}
    def post(self):
        return {"mes":"return post hello world"}

# api.add_resource(HelloWorldResource,'/')
# 3  收集类视图的注册信息 交给了蓝图bp
api.add_resource(HelloWorldResource,'/')

# 4. 将蓝图对象注册到全局的flask里面
app.register_blueprint(bp)

3 装饰器

使用method_decorators添加装饰器

  • 为类视图中的所有方法添加装饰器
  def decorator1(func):
      def wrapper(*args, **kwargs):
          print('decorator1')
          return func(*args, **kwargs)
      return wrapper


  def decorator2(func):
      def wrapper(*args, **kwargs):
          print('decorator2')
          return func(*args, **kwargs)
      return wrapper


  class DemoResource(Resource):
      method_decorators = [decorator1, decorator2]

      def get(self):
          return {'msg': 'get view'}

      def post(self):
          return {'msg': 'post view'}

 

  • 为类视图中不同的方法添加不同的装饰器
  class DemoResource(Resource):
      method_decorators = {
          'get': [decorator1, decorator2],
          'post': [decorator1]
      }

      # 使用了decorator1 decorator2两个装饰器
      def get(self):
          return {'msg': 'get view'}

      # 使用了decorator1 装饰器
      def post(self):
          return {'msg': 'post view'}

      # 未使用装饰器
      def put(self):
          return {'msg': 'put view'}

6.3 关于请求处理

Flask-RESTful 提供了RequestParser类,用来帮助我们检验和转换请求数据。

from flask_restful import reqparse

parser = reqparse.RequestParser()
parser.add_argument('rate', type=int, help='Rate cannot be converted', location='args')
parser.add_argument('name')
args = parser.parse_args()

使用步骤:

  1. 创建RequestParser对象

  2. RequestParser对象中添加需要检验或转换的参数声明

  3. 使用parse_args()方法启动检验处理

  4. 检验之后从检验结果中获取参数时可按照字典操作或对象属性操作

    args.rate
    或
    args['rate']
    

实列:

from flask import  Flask,Blueprint
from flask_restful import Resource,Api
from flask_restful.reqparse import RequestParser


app=Flask(__name__)
api=Api(app)

# demo?a=1&b=2
class DemoResource(Resource):
    def get(self):
        # 为了校验参数a
        # 1.创建RequestParser类对象
        rp = RequestParser()
        # 2 声明参数 参数的名字跟请求中的参数对应
        rp.add_argument('a')
        rp.add_argument('b')
        # 3 执行校验 返回校验对象
        req = rp.parse_args()
        # 4 把校验对象当做字典一样 拿参数,也可以当做对象 以属性的方式拿参数
        a = req['a']  # 字典
        b = req.b  # 对象
        return {"a":a}

api.add_resource(DemoResource,'/demo')

 

参数说明

1 required

描述请求是否一定要携带对应参数,默认值为False

  • True 强制要求携带

    若未携带,则校验失败,向客户端返回错误信息,状态码400

  • False 不强制要求携带

    若不强制携带,在客户端请求未携带参数时,取出值为None

class DemoResource(Resource):
    def get(self):
        rp = RequestParser()
        rp.add_argument('a', required=False)
        args = rp.parse_args()
        return {'msg': 'data={}'.format(args.a)}

2 help

参数检验错误时返回的错误描述信息

rp.add_argument('a', required=True, help='missing a param')

3 action

描述对于请求参数中出现多个同名参数时的处理方式

  • action='store' 保留出现的第一个, 默认
  • action='append' 以列表追加保存所有同名参数的值
rp.add_argument('a', required=True, help='missing a param', action='append')

4 type

描述参数应该匹配的类型,(1)可以使用python的标准数据类型string、int,使用标准类型的好处是如果能将参数转化为标准类型,则就转化为标准类型;(2)也可使用Flask-RESTful提供的检验方法,还可以自己定义

  • 标准类型

    rp.add_argument('a', type=int, required=True, help='missing a param', action='append')
    
  • Flask-RESTful提供

    检验类型方法在flask_restful.inputs模块中

    • url

    • regex(指定正则表达式)

      from flask_restful import inputs
      rp.add_argument('a', type=inputs.regex(r'^\d{2}&'))
      
    • natural 自然数0、1、2、3...

    • positive 正整数 1、2、3...

    • int_range(low ,high) 整数范围

      rp.add_argument('a', type=inputs.int_range(1, 10))
      
    • boolean

  • 自定义

    def mobile(mobile_str):
        """
        检验手机号格式
        :param mobile_str: str 被检验字符串
        :return: mobile_str
        """
        if re.match(r'^1[3-9]\d{9}$', mobile_str):
            return mobile_str
        else:
            raise ValueError('{} is not a valid mobile'.format(mobile_str))
    
    rp.add_argument('a', type=mobile)
    

     

 

5 location

描述参数应该在请求数据中出现的位置

# Look only in the POST body
parser.add_argument('name', type=int, location='form')

# Look only in the querystring
parser.add_argument('PageSize', type=int, location='args')

# From the request headers
parser.add_argument('User-Agent', location='headers')

# From http cookies
parser.add_argument('session_id', location='cookies')

# From json
parser.add_argument('user_id', location='json')

# From file uploads
parser.add_argument('picture', location='files')

也可指明多个位置

parser.add_argument('text', location=['headers', 'json'])

6.4 关于响应处理

flask_restful中返回的字典类型 可以自动转化为json了,

返回的数据从哪里来?如可以从数据库查询的来,但是查询数据库返回的一般是模型类对象 

我们需要借助于模型类转化工具,将模型类转化为字典 

1 序列化数据

Flask-RESTful 提供了marshal工具,用来帮助我们将数据序列化为特定格式的字典数据,以便作为视图的返回值。

(1)使用装饰器方式:marshal_with 需要提前预定义转化的字段

from flask_restful import Resource, fields, marshal_with

resource_fields = {
    'name': fields.String,
    'address': fields.String,
    'user_id': fields.Integer
}

class Todo(Resource):
    @marshal_with(resource_fields, envelope='resource')
    def get(self, **kwargs):
        return db_get_todo()  

# db_get_todo() 模型类对象 带入到了marshal_with装饰器,转化为 resource_fields 指定的类型。 

 

(2)也可以不使用装饰器,使用函数的方式:marshal

class Todo(Resource):
    def get(self, **kwargs):
        data = db_get_todo()
        return marshal(data, resource_fields)

示例

# 用来模拟要返回的数据对象的类
class User(object):
    def __init__(self, user_id, name, age):
        self.user_id = user_id
        self.name = name
        self.age = age

resoure_fields = {
        'user_id': fields.Integer,
        'name': fields.String
    }

class Demo1Resource(Resource):
    @marshal_with(resoure_fields, envelope='data1')
    def get(self):
        user = User(1, 'itcast', 12)
        return user

class Demo2Resource(Resource):
    def get(self):
        user = User(1, 'itcast', 12)
        return marshal(user, resoure_fields, envelope='data2')

 envelope 把返回的数据放到一个内嵌的字典中{“data1”:{要返回的字典}}

2 定制返回的JSON格式

需求

想要接口返回的JSON数据具有如下统一的格式

{"message": "描述信息", "data": {要返回的具体数据}}

在接口处理正常的情况下, message返回ok即可,但是若想每个接口正确返回时省略message字段

class DemoResource(Resource):
    def get(self):
        return {'user_id':1, 'name': 'itcast'}

对于诸如此类的接口,能否在某处统一格式化成上述需求格式?

{"message": "OK", "data": {'user_id':1, 'name': 'itcast'}}

解决

Flask-RESTful的Api对象提供了一个representation的装饰器,允许定制返回数据的呈现格式

api = Api(app)

@api.representation('application/json')
def handle_json(data, code, headers):
    # TODO 此处添加自定义处理
    return resp

Flask-RESTful原始对于json的格式处理方式如下:

代码出处:flask_restful.representations.json

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 we're in debug mode, and the indent is not set, we set it to a
    # reasonable value here.  Note that this won't override any existing value
    # that was set.  We also set the "sort_keys" value.
    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

为满足需求,做如下改动即可

@api.representation('application/json')
def output_json(data, code, headers=None):
    """Makes a Flask response with a JSON encoded body"""

    # 此处为自己添加***************
    if 'message' not in data:
        data = {
            'message': 'OK',
            'data': data
        }
    # **************************

    settings = current_app.config.get('RESTFUL_JSON', {})

    # If we're in debug mode, and the indent is not set, we set it to a
    # reasonable value here.  Note that this won't override any existing value
    # that was set.  We also set the "sort_keys" value.
    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

将返回的对象封装成json格式

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值