How to add a cursor() of a db connection to a sqlalchemy.orm session? "sqlalchemy.orm.exc.UnmappedInstanceError: Class 'builtins.int' is not mapped"

How to add a cursor() of a db connection to a sqlalchemy.orm session? "sqlalchemy.orm.exc.UnmappedInstanceError: Class 'builtins.int' is not mapped"

我在 Ubuntu 22.04 Docker 容器中 Python 3.10

我使用这些 apt 包:

mysql-client
libmysqlclient-dev

我使用以下 Python 软件包:

import mysqlclient==2.1.0
import sqlalchemy
# for the environment variables:
from dotenv import load_dotenv
# And to use sessions with flush, with the commit only at the end:
from sqlalchemy.orm import sessionmaker

sessionmaker 参数 autoflush 设置为 True。

我想在 sqlalchemy.orm 会话中添加一个删除,然后添加一个插入,这样我只在这两个命令运行良好时才提交。这样做的目的是更新一天内更新的 table。在不确定插入是否真的有效之前,我不想删除任何内容。

导致这个错误的Python部分代码(没有后续的插入命令):

DELETE_QUERY = f"""
    DELETE FROM {MY_TABLE} 
    WHERE checkdate = DATE(NOW())
"""

def delete_execute(sess, conn, query):
    """Function for deleting and adding to sess values 
    from the DB
    :param connection: pymsql connection to DB
    :param query: SQL query containing DELETE keyword
    :return: count of rows deleted
    """
    try:
        cursor = conn.cursor()
        sess.add(cursor.execute(query))
        # # Not yet commit, only after insertion:
        # connection.commit()
        # # Updates the objects of the session:
        # sess.flush()
        # # Not needed here since autoflush is set to True
        return cursor.rowcount, sess

engine = create_engine(CONNECTION)
# Session = sessionmaker(engine)
Session = sessionmaker(autocommit=False, autoflush=True, bind=engine)

# Connect to DB
logging.info("Connecting to DB ...")

# # with statement closes the connection automatically,
# # see https://docs.sqlalchemy.org/en/14/dialects/mysql.html
# # But the class does not have the needed __enter__ attribute
# 
# with engine.connect() as conn:
# # engine.connect() throws an error as well:
# conn = engine.connect() 
# # connection.cursor() AttributeError: 'Connection' object has no attribute 'cursor'
# 
conn = engine.raw_connection()

with Session() as sess:
    # The records only get deleted after commit
    # This only adds them to the session.
    deleted_records_count, sess = delete_execute(sess, conn, DELETE_QUERY)

我没有从其他链接获得关于相同错误的线索:

The User model contains many Task models and the Task model contains many Subtask models.

...insert a new User into a DB using SQLAlchemy and Marshmallow.

我是 sqlalchemy.orm 的新手,我担心我误解了什么。我想使用一个会话来删除和插入记录,我只想在两个命令的末尾提交。 我使用游标进行删除。我怎样才能嵌入光标 - 它只能通过 conn = engine.raw_connection() 中的 conn 对象使用 - 以便只有在下一个插入任务也能正常工作时才能完成任务?我不能只将它添加到会话中:

sess.add(cursor.execute(query))

抛出:

sqlalchemy.orm.exc.UnmappedInstanceError: Class 'builtins.int' is not mapped

错误详情:

Traceback (most recent call last):
  File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/MY_PROJECT/main.py", line 574, in <module>
    get_sql_and_save_as_csv_in_gcs(request)
  File "/MY_PROJECT/main.py", line 489, in get_sql_and_save_as_csv_in_gcs
    deleted_records_count, sess = delete_execute(sess, conn, DELETE_QUERY)
  File "/usr/local/lib/python3.9/dist-packages/dryable/__init__.py", line 34, in _decorated
    return function( * args, ** kwargs )
  File "/MY_PROJECT/main.py", line 204, in delete_execute
    sess.add(cursor.execute(query))
  File "/usr/local/lib/python3.9/dist-packages/sqlalchemy/orm/session.py", line 2601, in add
    util.raise_(
  File "/usr/local/lib/python3.9/dist-packages/sqlalchemy/util/compat.py", line 207, in raise_
    raise exception
sqlalchemy.orm.exc.UnmappedInstanceError: Class 'builtins.int' is not mapped

那我应该怎么做呢?

from sqlalchemy.sql import func

with Session() as session:
    # Model here is the orm Model, you could also do something similar
    # using sqlalchemy's core layer.
    cursor_result = session.query(Model).filter(Model.checkdate == func.now()).delete()
    deleted_rowcount = cursor_result.rowcount
    # This will insert each model at a time, maybe you want to do something
    # with better performance here.
    session.add_all(new_models)
    # commit delete and perform inserts
    session.commit()

原来使用上面的orm delete returns一个游标,你可以在这里阅读:update-and-delete-with-arbitrary-where-clause

核心版本,使用 table 对象,应该与 session.execute 一起工作,你可以在这里阅读:getting-affected-row-count-from-update-delete