【问题标题】:RESTful interface in Flask and issues serializingFlask 中的 RESTful 接口和序列化问题
【发布时间】:2012-11-24 06:55:52
【问题描述】:

我正在学习 Backbone.js 和 Flask(以及 Flask-sqlalchemy)。我之所以选择 Flask,是因为我读到它与实现 RESTful 接口的 Backbone 配合得很好。我目前正在关注使用(或多或少)此模型的course

class Tasks(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(80), unique=True)
    completed = db.Column(db.Boolean, unique=False, default=False)

    def __init__(self, title, completed):
        self.title = title
        self.completed = completed

    def json_dump(self):
        return dict(title=self.title, completed=self.completed)

    def __repr__(self):
        return '<Task %r>' % self.title

我必须添加一个 json_dump 方法才能将 JSON 发送到浏览器。否则,我会收到object is not JSON serializable 之类的错误,所以我的第一个问题是:

有没有更好的方法在 Flask 中进行序列化?似乎有些对象是可序列化的,而另一些则不是,但总的来说,它并不像我预期的那么容易。

一段时间后,我最终得到了以下视图来处理每种类型的请求:

@app.route('/tasks')
def tasks():
    tasks = Tasks.query.all()
    serialized = json.dumps([c.json_dump() for c in tasks])
    return serialized

@app.route('/tasks/<id>', methods=['GET'])
def get_task(id):
    tasks = Tasks.query.get(int(id))
    serialized = json.dumps(tasks.json_dump())
    return serialized

@app.route('/tasks/<id>', methods=['PUT'])
def put_task(id):
    task = Tasks.query.get(int(id))
    task.title = request.json['title']
    task.completed = request.json['completed']
    db.session.add(task)
    db.session.commit()
    serialized = json.dumps(task.json_dump())
    return serialized

@app.route('/tasks/<id>', methods=['DELETE'])
def delete_task(id):
    task = Tasks.query.get(int(id))
    db.session.delete(task)
    db.session.commit()
    serialized = json.dumps(task.json_dump())
    return serialized

@app.route('/tasks', methods=['POST'])
def post_task():
    task = Tasks(request.json['title'], request.json['completed'])
    db.session.add(task)
    db.session.commit()
    serialized = json.dumps(task.json_dump())
    return serialized

在我看来,这似乎有点冗长。同样,实施它们的正确方法是什么?我见过一些 extensions 在 Flask 中提供 RESTful 接口,但这些对我来说看起来相当复杂。

谢谢

【问题讨论】:

    标签: json rest serialization flask flask-sqlalchemy


    【解决方案1】:

    老实说,我会使用一个模块来做到这一点。我们已经为一些 API 使用了 Flask-Restless,你可以看看:

    https://flask-restless.readthedocs.org/en/latest/

    但是,如果您想构建自己的,您可以使用 SQLAlchemy 的自省功能将您的对象输出为键/值对。

    http://docs.sqlalchemy.org/en/rel_0_7/core/schema.html#metadata-reflection

    类似这样的东西,虽然我总是要反复检查我的语法是否正确,所以把它作为指导而不是工作代码。

    @app.route('/tasks')
    def tasks():
        tasks = Tasks.query.all()
    
        output = []
        for task in tasks:
          row = {}
    
          for field in Tasks.__table__.c:
            row[str(field)] = getattr(task, field, None)
    
          output.append(row)
    
        return jsonify(data=output)
    

    我发现这个问题可能对您有更多帮助。我熟悉 SQLAlchemy 0.7,看起来 0.8 添加了一些更好的自省技术:

    SQLAlchemy introspection

    【讨论】:

    • 抱歉回复晚了。是的,我认为您引用的项目与我的想法相同。顺便说一句,我正在使用flask-sqlalchemy,所以我不知道如何理解sqlalchemy的内省。我想我可以使用第一个选项,但我期待别的东西。
    • 这绝对不是为了娇气,但它很强大。你可以在 Flask-SQLAlchemy 中使用这种方法,事实上,我在那里给出的示例使用了 Flask-SQLAlchemy。我在我们的应用程序中使用它来进行自定义数据提取和其他深层魔法。
    • 好的,我会尝试实现它。除了管理请求和设置路由之外,您是否知道这些内置方法是否还在做其他事情,或者基本上仅此而已。
    • 使用自省序列化模型的示例:wakatime.com/blog/32-part-1-sqlalchemy-models-to-json
    【解决方案2】:

    Flask 提供了jsonify 函数来做到这一点。查看它的工作here

    您的 json_dump 方法是正确的,尽管代码可以简洁。看这段代码sn-p

    @app.route('/tasks')
    def tasks():
        tasks = Tasks.query.all()
        return jsonify(data=[c.json_dump() for c in tasks])
    

    【讨论】:

    猜你喜欢
    • 2013-10-25
    • 2011-11-23
    • 2021-10-17
    • 2011-06-28
    • 2021-09-19
    • 1970-01-01
    • 2021-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多