gpt4 book ai didi

python - 添加 prefix_with 子句以插入特定类

转载 作者:太空宇宙 更新时间:2023-11-04 01:27:54 26 4
gpt4 key购买 nike

如何自定义 SQLAlchemy 中每个模型类的 prefix_with 以便每个模型类都可以有不同的插入语句?

我实际上想要将 OR IGNORE 子句添加到某些类中。

PS:我对 SQLAlchemy 比较陌生

最佳答案

ORM 没有关于它如何生成 insert() 的钩子(Hook)构造,所以你在这里能做的最好的就是拦截 insert()Table 的陈述级别,这在这里可能已经足够好了,因为您想对这些表全面执行“忽略”操作,这是一个使用类装饰器使其通用的方法。我们正在使用 before_execute此处重写某些事件 insert()构造:

from sqlalchemy import event
from sqlalchemy.engine import Engine
from sqlalchemy.sql import Insert

_ignore_tables = set()

@event.listens_for(Engine, "before_execute", retval=True)
def _ignore_insert(conn, element, multiparams, params):
if isinstance(element, Insert) and \
element.table.name in _ignore_tables:
element = element.prefix_with("IGNORE")
return element, multiparams, params

def ignore_inserts(cls):
_ignore_tables.add(cls.__table__.name)
return cls

if __name__ == '__main__':
from sqlalchemy import Column, Integer, create_engine
from sqlalchemy.orm import Session
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class A(Base):
__tablename__ = 'a'

id = Column(Integer, primary_key=True)

@ignore_inserts
class B(Base):
__tablename__ = 'b'

id = Column(Integer, primary_key=True)

@ignore_inserts
class C(Base):
__tablename__ = 'c'

id = Column(Integer, primary_key=True)

e = create_engine("mysql://scott:tiger@localhost/test", echo=True)
Base.metadata.drop_all(e)
Base.metadata.create_all(e)

s = Session(e)

s.add_all([A(), B(), C()])
s.commit()

像那样全面使用它会让我感到紧张,这是一个不同的版本,因此您可以使用上下文管理器为具有特定 Session 的特定表设置规则:

from sqlalchemy import event
from sqlalchemy.engine import Engine
from sqlalchemy.sql import Insert
from contextlib import contextmanager

@event.listens_for(Engine, "before_execute", retval=True)
def _ignore_insert(conn, element, multiparams, params):
if isinstance(element, Insert) and \
'ignore_tables' in conn.info and \
element.table.name in conn.info['ignore_tables']:
element = element.prefix_with("IGNORE")
return element, multiparams, params


@contextmanager
def ignore_inserts(session, names):
conn = session.connection()
info = conn.info # hold onto info so we can still
# get to it when the Connection is closed
previous = info.get('ignore_tables', ())
try:
info['ignore_tables'] = set(names)
yield
finally:
info['ignore_tables'] = previous

if __name__ == '__main__':
from sqlalchemy import Column, Integer, create_engine
from sqlalchemy.orm import Session
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class A(Base):
__tablename__ = 'a'

id = Column(Integer, primary_key=True)

class B(Base):
__tablename__ = 'b'

id = Column(Integer, primary_key=True)

class C(Base):
__tablename__ = 'c'

id = Column(Integer, primary_key=True)

e = create_engine("mysql://scott:tiger@localhost/test", echo=True)
Base.metadata.drop_all(e)
Base.metadata.create_all(e)

s = Session(e)

with ignore_inserts(s, ['b']):
s.add_all([A(), B(), C()])
s.commit()

with ignore_inserts(s, ['a', 'c']):
s.add_all([A(), B(), C()])
s.commit()

关于python - 添加 prefix_with 子句以插入特定类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16459803/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com