【问题标题】:How do I read the parameter of the GET request in a RESTful Flask/SQLAlchemy/Marshmallow environment如何在 RESTful Flask/SQLAlchemy/Marshmallow 环境中读取 GET 请求的参数
【发布时间】:2019-01-29 00:01:10
【问题描述】:

圣诞节前我正在学习一些教程,现在我正在尝试从我离开的地方继续学习。 尝试通过构建一些简单的 API 端点来自学 REST。我的困惑来自于我找不到我正在使用的教程,而且似乎有几种不同的方法可以解决这个问题。所以现在我不确定正确的方法是什么。 该代码适用于返回数据库中的所有客户,现在我想根据他们的 Id 返回一个特定的客户

好的,这就是我所拥有的......

我有一个 app.py,它定义了这样的资源:

api.add_resource(CustomerResource, '/Customer')

我有一个models.py,它定义了这样的客户类:

ma = Marshmallow()
db = SQLAlchemy()

class Customer(db.Model):
    __tablename__ = 'customers'
    __table_args__ = {"schema":"business"}
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.Text, nullable=False)
    status = db.Column(db.Integer, nullable=False)

class CustomerSchema(ma.Schema):
    id = fields.Integer()
    name = fields.String(required=True)
    status = fields.Integer(required=True)

我有 customer.py 将客户类定义为:

customers_schema = CustomerSchema(many=True)
customer_schema = CustomerSchema()

class CustomerResource(Resource):
    def get(self):
        customers = Customer.query.all()
        customers = customers_schema.dump(customers)
        return {'status': 'success', 'data': customers}, 200

我尝试过使用 request.args,但我不认为这是正确的方法,因为它会变得不支持。

因此,以上所有内容都适用于 GET 成功返回所有客户。但现在我希望能够使用 GET http://127.0.0.1:5000/api/Customer/10 并返回客户 ID = 10 的详细信息

我不确定是否需要定义新资源,或者是否可以修改现有 CustomerResource 以测试参数是否存在。

任何指导表示赞赏...

【问题讨论】:

    标签: python-3.x rest get flask-sqlalchemy marshmallow


    【解决方案1】:

    是的,你是对的,不要使用request.args 方法,而是创建另一个资源。请记住,api.add_resource 本质上只是将处理程序映射到 RESTFUL 端点。如果您有很多重复的业务逻辑代码在端点之间共享,我建议您将该业务逻辑抽象为一个辅助函数在其中使用这个辅助函数您的资源定义, 但在这种特殊情况下,这不是必需的。我会考虑做以下事情:

    app.py:

    api.add_resource(CustomerList, '/Customer')
    api.add_resource(Customer, '/Customer/<int:id>')
    

    我会将 customer.py 重命名为 routes.py 之类的名称,其中包含以下内容:

    class CustomerList(Resource):
        def get(self):
            customers = Customer.query.all()
            customers = customers_schema.dump(customers)
            return {'status': 'success', 'data': customers}, 200
    
    class Customer(Resource):
        def get(self, id):
            customer = Customer.query.filter_by(id=id).first()
            customer, errors = customers_schema.dump(customer)
            if errors:
               return jsonify(errors), 422
            return customer, 200
    

    保持您的 models.py 文件原样,我会考虑使用flask 提供的jsonify 方法在您的RESTFUL 端点中返回您的数据。我已经在特定的客户端点中展示了一个示例。

    希望对您有所帮助!

    【讨论】:

    • 谢谢内森。我已经按照您的建议进行了更改。对所有客户的要求仍然有效。对特定客户的请求导致 TypeError: 'Customer' object is not iterable error for the line "customer = Customer.query.filter_by(id=id).first()"。知道为什么吗?
    • 嗨,这可能是一个转换错误,因为您的客户表的主键是一个整数尝试将您的客户特定资源更改为以下内容:api.add_resource(Customer, '/Customer/ ' 并让我知道这是否解决了问题。如果没有,我可以看看你的代码,如果你给我一个链接:)
    • 谢谢你,内森。不可迭代的错误是我的错误,我已经纠正了它。我确实有另一个问题,尽管在您建议 customer, errors = customers_schema.dump(customer) 的行中它会导致以下错误 ValueError: too many values to unpack (expected 2) 我已经编辑了原始帖子以显示声明架构的位置。但恐怕我根本不了解这部分 - 它来自教程
    • OK 回答我之前的评论。问题是我使用的 Marshmallow 版本不再返回数据、错误——它只是返回反序列化的数据。根据这个答案link
    • 再次感谢您,这正是我想要的!
    最近更新 更多