ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Flask 学习-48.Flask-RESTX 使用api.model() 模型工厂

2022-09-05 14:04:15  阅读:221  来源: 互联网

标签:RESTX resource 48 Flask fields self api Resource def


前言

model()工厂允许您将模型实例化并注册到您的API或Namespace.

api.model() 工厂

有2种使用方式,第一种直接使用 api.model

my_fields = api.model('MyModel', {
    'name': fields.String,
    'age': fields.Integer(min=0)
})

第二种间接注册到api,以下方式是等价的

# Equivalent to
my_fields = Model('MyModel', {
    'name': fields.String,
    'age': fields.Integer(min=0)
})
api.models[my_fields.name] = my_fields

使用示例

user模型

class Users(db.Model):
    __tablename__ = 'user'  # 数据库表名
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(50), unique=True, nullable=False)
    password = db.Column(db.String(128), nullable=False)
    is_active = db.Column(db.Boolean, default=1)
    email = db.Column(db.String(64), nullable=True)
    create_time = db.Column(db.DateTime, default=datetime.now)
    update_time = db.Column(db.DateTime, onupdate=datetime.now, default=datetime.now)

    def hash_password(self, password):
        """密码加密"""
        self.password = sha256_crypt.encrypt(password)

    def verify_password(self, password):
        """校验密码"""
        return sha256_crypt.verify(password, self.password)

    def __repr__(self):
        return f"<Users(id='{self.id}', username='{self.username}'...)>"

校验请求入参,除了之前学到的 RequestParser 来定义预期的输入:

@api.route('/api/user', endpoint='user')
class UserView(Resource):

    def post(self):
        """add user"""
        parser = reqparse.RequestParser()
        parser.add_argument('username', required=True, type=str, help='username is required')
        parser.add_argument('password', required=True, type=str, help='password is required')
        args = parser.parse_args()
        print(f'请求参数: {args}')
        # 保存数据库
        return {"msg": "create success"}

也可以使用api.model() 的方法来校验请求入参, 以下方式是等价的

from flask_restx import Resource, fields

user_input = api.model('UserModel', {
    'username': fields.String(required=True),
    'password': fields.String(required=True)
})


@api.route('/api/user', endpoint='user')
class UserView(Resource):

    @api.expect(user_input, validate=True)
    def post(self):
        """add user"""
        print(f'请求参数: {api.payload}')
        # 保存数据库
        return {"msg": "create success"}

@api.expect 装饰器

装饰器@api.expect() 允许您指定预期的输入字段。它接受一个可选的布尔参数 validate,指示是否应验证有效payload 参数。
RESTX_VALIDATE可以通过将配置设置为True 或传递validate=True给 API 构造函数来全局自定义验证行为。

以下示例是等效的, 未设置validate=True 功能等价于@api.expect() 功能跟 api.doc() 一样(api.doc() 用于 swagger 文档输出)

使用@api.expect()装饰器:

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>')
class MyResource(Resource):
    @api.expect(resource_fields)
    def get(self):
        pass

使用api.doc()装饰器:

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>')
class MyResource(Resource):
    @api.doc(body=resource_fields)
    def get(self):
        pass

您可以将列表指定为预期输入:

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>')
class MyResource(Resource):
    @api.expect([resource_fields])
    def get(self):
        pass

您可以使用RequestParser来定义预期的输入:

parser = api.parser()
parser.add_argument('param', type=int, help='Some param', location='form')
parser.add_argument('in_files', type=FileStorage, location='files')


@api.route('/with-parser/', endpoint='with-parser')
class WithParserResource(restx.Resource):
    @api.expect(parser)
    def get(self):
        return {}

启用或禁用 validate 验证:

可以在特定端点上启用或禁用验证:

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>')
class MyResource(Resource):
    # Payload validation disabled  禁用validate 校验入参
    @api.expect(resource_fields)
    def post(self):
        pass

    # Payload validation enabled  启用validate 校验入参
    @api.expect(resource_fields, validate=True)
    def post(self):
        pass

通过配置进行应用程序范围验证的示例:

app.config['RESTX_VALIDATE'] = True

api = Api(app)

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>')
class MyResource(Resource):
    # Payload validation enabled
    @api.expect(resource_fields)
    def post(self):
        pass

    # Payload validation disabled
    @api.expect(resource_fields, validate=False)
    def post(self):
        pass

通过构造函数进行应用程序范围验证的示例:

api = Api(app, validate=True)

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>')
class MyResource(Resource):
    # Payload validation enabled
    @api.expect(resource_fields)
    def post(self):
        pass

    # Payload validation disabled
    @api.expect(resource_fields, validate=False)
    def post(self):
        pass

@api.marshal_with()装饰器

这个装饰器像原始marshal_with()装饰器一样工作,不同之处在于它记录了方法。可选参数code允许您指定预期的 HTTP 状态代码(默认为 200)。可选参数as_list允许您指定对象是否作为列表返回。

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>', endpoint='my-resource')
class MyResource(Resource):
    @api.marshal_with(resource_fields, as_list=True)
    def get(self):
        return get_objects()

    @api.marshal_with(resource_fields, code=201)
    def post(self):
        return create_object(), 201

Api.marshal_list_with() 装饰器严格等价于 Api.marshal_with(fields, as_list=True)()

resource_fields = api.model('Resource', {
    'name': fields.String,
})

@api.route('/my-resource/<id>', endpoint='my-resource')
class MyResource(Resource):
    @api.marshal_list_with(resource_fields)
    def get(self):
        return get_objects()

    @api.marshal_with(resource_fields)
    def post(self):
        return create_object()

使用示例

post 请求校验请求入参,get 请求查询数据序列化输出内容


from flask_restx import Resource, fields

user_input = api.model('UserModel', {
    'username': fields.String(required=True),
    'password': fields.String(required=True)
})

out_fields = api.model('UserInfo', {
    'username': fields.String,
    'email': fields.String,
    'create_time': fields.DateTime(dt_format='rfc822')
})


@api.route('/api/user', endpoint='user')
class UserView(Resource):

    @api.marshal_with(out_fields, envelope='users')
    def get(self):
        """查询全部"""
        users = models.Users.query.all()
        return users

    @api.expect(user_input, validate=True)
    def post(self):
        """add user"""
        print(f'请求参数: {api.payload}')
        # 保存数据库
        return {"msg": "create success"}

get请求查询结果

GET http://127.0.0.1:5000/api/user HTTP/1.1


{
    "users": [
        {
            "username": "test",
            "email": null,
            "create_time": "Mon, 05 Sep 2022 11:13:16 -0000"
        },
        {
            "username": "test1",
            "email": null,
            "create_time": "Mon, 05 Sep 2022 13:10:41 -0000"
        },
        {
            "username": "test12",
            "email": null,
            "create_time": "Mon, 05 Sep 2022 13:10:55 -0000"
        }
    ]
}

标签:RESTX,resource,48,Flask,fields,self,api,Resource,def
来源: https://www.cnblogs.com/yoyoketang/p/16657864.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有