【问题标题】:SQLAlchemy bulk insert from JSON data来自 JSON 数据的 SQLAlchemy 批量插入
【发布时间】:2018-11-05 06:31:08
【问题描述】:

我第一次尝试使用 ORM,试图了解它是如何工作的,但遇到了一些挑战:

我想要做的是,将来自 API 的 JSON 拟合到 SQLAlchemy 模型中,然后将所有条目批量插入到我的数据库中。但由于某种原因,我在 SQLAlchemy 中遇到了错误。

根据我对错误的理解,在某个时间点,将数据分配给我的模型时,它被转换为字典,而我认为它应该是class objects 的列表。

我的预期结果是成功插入所有条目。任何人都可以帮助弄清楚我可能做错了什么吗?

欣赏。*

错误

sqlalchemy.exc.ProgrammingError:
(mysql.connector.errors.ProgrammingError) 
Failed processing pyformat-parameters;
Python 'dict' cannot be converted to a MySQL type

JSON:

{
"all_orders": [
    {
    "id": 456215587,
    "created_at": "2018-11-04T23:18:18-02:00",
    "order_number": null,
    },
    {
    "id": null,
    "created_at": "2018-11-04T23:18:18-02:00",
    "order_number": 1982,
    }]
}

函数

def update_orders(all_orders):

    cursor = db_cursor()
    session = db_session()
    orders_entries = []

    for orders in all_orders:

       order_id        = orders.get("id", {})
       order_number    = orders.get("order_number", {})
       created_at      = orders.get("created_at", {})

       new_entry = SalesOrders(order_id=order_id,
                               order_number=order_number,
                               created_at=created_at)

       orders_entries.append(new_entry)

    session.add_all(orders_entries)
    session.commit()

模型

class SalesOrders(db.Model):
    __tablename__ = 'sales_orders'

    id = Column(Integer, nullable=False, index=True)
    order_id = Column(String(50), primary_key=True, server_default=text("''"))
    order_number = Column(String(50))
    created_at = Column(String(100))

编辑以使其可验证。 函数 .get() 正在创建字典,而不是 None 对象,并且 SQLAlchemy 无法插入 Python 字典。

【问题讨论】:

  • "PS:没关系字段名称,我编辑了代码以使其更小。"不是不提供minimal reproducible example 的借口,强调可验证。您提供的代码和数据包含多个错误,但不是您要询问的错误。
  • 你是对的。我将尝试在不粘贴大量代码的情况下使其可验证。
  • @IljaEverilä 对其进行了编辑以使其可验证并最终发现了问题。感谢您的意见。

标签: python flask sqlalchemy flask-sqlalchemy


【解决方案1】:

当使用get() 函数时,SQLAlchemy 得到一个字典,这在 SQL 插入函数中是不期望的,这会产生错误。 要使其工作,只需传递 None 对象而不是 {}

import os
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import *


basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'main.db')

db = SQLAlchemy(app)


data = {
   "all_orders": [
      {
         "id": 456213548,
         "created_at": "2018-11-04T23:18:18-02:00",
         "number": null
      },
      {
         "id":4562222222,
         "created_at": "2018-11-04T23:18:18-02:00",
         "number": 1982,
      }
   ]
}


class SalesOrders(db.Model):
    __tablename__ = 'sales_orders'

    order_id = db.Column(db.String(50), primary_key=True, server_default='')
    order_number = db.Column(db.String(50))
    created_at = db.Column(db.String(50))


def update_orders(data):
    orders_entries = []
    for orders in data["all_orders"]:
        new_entry = SalesOrders(order_id=orders['id'],
                                order_number=orders['number'])
        orders_entries.append(new_entry)
    db.session.add_all(orders_entries)
    db.session.commit()


if __name__ == "__main__":
    app.run(debug=True)

例子:

>>> import app
>>> from app import *
>>> data
{'all_orders': [{'id': 456213548, 'created_at': '2018-11-04T23:18:18-02:00', 'number': 1982}, {'id': 4562222222, 'created_at': '2018-11-04T23:18:18-02:00', 'number': 1982}]}
>>> update_orders(data)
>>> SalesOrders.query.all()
[<SalesOrders 456213548>, <SalesOrders 4562222222>]

【讨论】:

  • 谢谢。正如上面一位用户所指出的,这个问题无法正确验证,因为 ID 确实是唯一的。发生的事情是我使用get() 函数和{} 作为参数,所以SQLAlchemy 将输入理解为Python Dict。如果您可以调整答案以记录“真正的”问题”,我会接受。谢谢。
  • order_id=orders['id']order_id=orders.get('id', default='some_value') 之间的区别在于,如果未找到 id 密钥,第一种方法会引发 KeyError,而第二种方法默认为 some_value。在您的情况下,它默认为空字典{}
  • 谢谢,就是这样。由于对get()函数缺乏了解,我花了很长时间才意识到。
猜你喜欢
  • 2015-11-06
  • 2022-01-20
  • 2017-01-20
  • 2018-07-29
  • 2010-11-24
  • 2011-04-09
  • 1970-01-01
  • 1970-01-01
  • 2018-09-18
相关资源
最近更新 更多