【问题标题】:Flask-Sqlalchemy: DB queries don't return new dataFlask-Sqlalchemy:数据库查询不返回新数据
【发布时间】:2015-10-18 11:56:42
【问题描述】:

我正在构建一个应用程序,它从一项服务接收 webhook,将数据存储在数据库中,然后通过 API 提供数据。

我能够成功地将数据添加到我的应用程序中,但是当我查询数据库时,我只收到了上次启动应用程序时数据库中的第一次提交。

例如,如果我启动应用程序时 Orders 表中有 26 个订单,然后触发 webhook,Order.query.all() 将返回 27 个订单,直到我重新启动应用程序,无论表中实际有多少订单 (我可以使用 MySQL 进行验证)。

这是一个用于向表中插入数据的类的示例:

@webhook.route('/order/insert', methods=['POST'])
def insert_orders():
    soda_json = request.json
    db.session.add(Order(
        order_id=soda_json['id'],  
        created_at=datetime.datetime.now(),
        currency=soda_json['currency'],
        total_line_items_price=soda_json['total_line_items_price'],
        refunds=sum(float(i) for i in soda_json['refunds'] if soda_json['refunds']),
        shipping_lines_price=sum([float(line['price']) for line in soda_json['shipping_lines']]),
        note=soda_json['note']
    ))
db.session.commit()
return '200'

这是我用于测试的基本 API 方法:

order_test = Order.query.all()

@api.route('/display', methods=['POST', 'GET'])
def display_test():
    return jsonify(json_list=[i.serialize for i in order_test]), '200'

为了始终获取最新数据,我缺少什么?

【问题讨论】:

  • 如何填充order_test?你能提供从数据库中填充它的代码吗
  • 刚刚添加的order_test
  • 试试return jsonify(json_list = order_test)。如果这不起作用,请尝试return jsonify(json_list = order_test.all())

标签: python mysql flask flask-sqlalchemy


【解决方案1】:

据我所知,order_list 仅在启动该视图时才被填充。因此,如果您将该行代码移动到您的路由调用中,那么每次调用该路由时都会刷新它。

例如

@api.route('/display', methods=['POST', 'GET'])
def display_test():
    order_test = Order.query.all()
    return jsonify(json_list=[i.serialize for i in order_test]), '200'

从您目前所说的看来,无论新数据发送到网络挂钩多少次,您似乎只能向数据库添加一条新记录,并且如果您重新启动 API,那么您就是回到第一格,新记录不再存在。

对我来说,在 webhook 中提交事务似乎是一个问题,因为在调用 db.session.add() 之后,数据不会保存到数据库中,因此事务保持打开状态,因此当添加新数据时,它可能会覆盖上一次调用中的数据,然后当您结束 API 时,事务要么 committed 要么 rollbacked(可以'不记得烧瓶炼金术的默认动作)。您可能需要检查数据本身并查看调用 webhook 后第 51 行中返回的数据,并查看在将新数据发送到 webhook 后它是否发生变化。

如果您还比较上面的 webhook 代码和下面的提交和返回行是不同的。在您的情况下,它们位于不同的选项卡行上,并且在 webhook 函数之外,并且在调用 webhook 时不会运行,因此会有一个打开的事务。

@webhook.route('/order/insert', methods=['POST'])
def insert_orders():
    soda_json = request.json
    db.session.add(Order(
        order_id=soda_json['id'],  
        created_at=datetime.datetime.now(),
        currency=soda_json['currency'],
        total_line_items_price=soda_json['total_line_items_price'],
        refunds=sum(float(i) for i in soda_json['refunds'] if soda_json['refunds']),
        shipping_lines_price=sum([float(line['price']) for line in soda_json['shipping_lines']]),
        note=soda_json['note']
    ))
    db.session.commit()
    return '200'

【讨论】:

  • 不幸的是,这似乎没有什么区别 - 仍然从查询中获得与启动应用程序时相同数量的订单。
  • hmm 你确定添加后可以在数据库中看到新记录吗?您可以添加多个新记录并在那里查看它们吗?关闭 API 后还能看到数据库中的记录吗?
  • 仔细观察,这种行为似乎更奇怪:1. 启动应用程序 2. 检查查询,50 行 3. 检查 MySQL,50 行 4. 触发 Webhook,我的应用程序 200 OK 5. 检查 MySQL , 51 Rows 6. Check Query, 51 Rows 7. Trigger Webhook, 200 OK from my app 8. Check MySQL, 52 Rows 9. Check Query, 51 Rows 所以看起来它实际上是在显示 first仅插入我的会话中。
  • 当你关闭 API 时,是 51 行还是 50 行呢?数据如何仅显示输入的最新值?因为我想知道提交是否正确发生。当我复制 webhook 代码时,我看到提交在 webhook 函数之外
  • "...我想知道提交是否正确。当我复制 webhook 代码时,我看到提交在 webhook 函数之外"
【解决方案2】:

看起来查询中方法的顺序可能是个问题。

from my_app.models import Order

order_test = Order.query.all()

这就是教程中的结构 (https://pythonhosted.org/Flask-SQLAlchemy/queries.html#querying-records),但看起来这可能只是查看原始导入模型中的数据。请随时纠正我。

在烧瓶外壳中的类似操作中,我已经成功地在使用此查询结构提交后立即获取实时数据:

db.session.query([model]).all()

因此,API 方法的工作示例可能是:

@api.route('/display', methods=['POST', 'GET'])
def display_test():
    order_test = db.session.query(Order).all()
    return jsonify(json_list=[i.serialize for i in order_test]), '200'

【讨论】:

  • 做到了!现在我的应用程序正在获取最新数据。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-16
  • 1970-01-01
相关资源
最近更新 更多