SQLALchemy 使用来自 kwargs 的 in 子句进行更新
SQLALchemy update with in clause from kwargs
我正在尝试编写一个将 kwargs 作为参数的函数,并且
生成更新语句,其中要更新的行是
在 in 子句中指定。
这是我的资料:
def update_by_in(self, **kwargs):
filter_group = []
for col in kwargs['query_params']:
attr = getattr(self.model_class, col)
filter_group.append(attr.in_(tuple(kwargs['query_params'][col])))
self._session.query(self.model_class).\
filter(*filter_group).\
update(kwargs['values'])
self.update_by_in(
**{'query_params': {'companyCode': ['A', 'B', 'C']},
'values': {'portfolioName': 'test'}}
)
sqlalchemy.orm.evaluator.UnevaluatableError: Cannot evaluate clauselist with operator <function comma_op at 0x7f33f037adc0>
为了验证查询部分是否正常工作,我从
打印了 return
self._session.query(self.model_class).filter(*filter_group).all()
[<common.models_dec_core.Portfolio object at 0x7f2b98157f40>]
也尝试对传递给更新的字典进行硬编码,但得到了同样的错误。
我做错了什么?
我通过将 synchronize_session='fetch' 添加到
更新。真的很想知道为什么需要 - 我有
类似的代码,但不使用变量(模型和列
是硬编码的)并且在没有 synchronize_session.
的情况下也能工作
sqlalchemy 1.4.2 不会出现此问题,但 sqlalchemy 1.3.16 会出现此问题。
我认为这是因为默认的 synchronize_session
值是 "evaluate"
并且它无法解决 1.3.16 中的 in_
条件。
以下使用 or_
的条件使用默认值,但使用 in_
的条件需要将 synchronize_session
设置为 "fetch"
。
示例 or_
和 in_
from datetime import datetime, date
from sqlalchemy import (
create_engine,
Text,
Integer,
String,
ForeignKey,
UniqueConstraint,
update,
DateTime,
Date,
Boolean,
LargeBinary,
)
from sqlalchemy.schema import (
Table,
Column,
MetaData,
)
from sqlalchemy.sql import select, and_, or_, func
from sqlalchemy.orm import relationship
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
engine = create_engine("sqlite://", echo=False)
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
code = Column(String(1), nullable=False)
portfolio = Column(String(100), nullable=True)
Base.metadata.create_all(engine)
def update_by_or(session, model_class, **kwargs):
filter_group = []
for col in kwargs['query_params']:
attr = getattr(model_class, col)
filter_group.append(or_(*[attr == v for v in kwargs['query_params'][col]]))
session.query(model_class).\
filter(filter_group[0]).\
update(kwargs['values'])
def update_by_in(session, model_class, **kwargs):
filter_group = []
for col in kwargs['query_params']:
attr = getattr(model_class, col)
filter_group.append(attr.in_(kwargs['query_params'][col]))
session.query(model_class).\
filter(filter_group[0]).\
update(kwargs['values'], synchronize_session='fetch')
def print_users(session):
for u in session.query(User).all():
print (u.id, u.name, u.code, u.portfolio)
session = Session(engine)
session.add(User(name='One', code='A'))
session.add(User(name='Two', code='B'))
session.add(User(name='Three', code='C'))
session.add(User(name='Four', code='D'))
session.commit()
print_users(session)
update_by_in(session, User, **{'query_params': {'code': ['A', 'B', 'C']},
'values': {User.portfolio: 'test1'}})
session.commit()
print_users(session)
update_by_in(session, User, **{'query_params': {'code': ['A', 'B', 'C']},
'values': {User.portfolio: 'test2'}})
session.commit()
print_users(session)
输出
1 One A None
2 Two B None
3 Three C None
4 Four D None
1 One A test1
2 Two B test1
3 Three C test1
4 Four D None
1 One A test2
2 Two B test2
3 Three C test2
4 Four D None
虽然我收到的异常是:
sqlalchemy.exc.InvalidRequestError: Could not evaluate current criteria in Python: "Cannot evaluate clauselist with operator <function comma_op at 0x7f7c082821e0>". Specify 'fetch' or False for the synchronize_session parameter.
我正在尝试编写一个将 kwargs 作为参数的函数,并且 生成更新语句,其中要更新的行是 在 in 子句中指定。
这是我的资料:
def update_by_in(self, **kwargs):
filter_group = []
for col in kwargs['query_params']:
attr = getattr(self.model_class, col)
filter_group.append(attr.in_(tuple(kwargs['query_params'][col])))
self._session.query(self.model_class).\
filter(*filter_group).\
update(kwargs['values'])
self.update_by_in(
**{'query_params': {'companyCode': ['A', 'B', 'C']},
'values': {'portfolioName': 'test'}}
)
sqlalchemy.orm.evaluator.UnevaluatableError: Cannot evaluate clauselist with operator <function comma_op at 0x7f33f037adc0>
为了验证查询部分是否正常工作,我从
打印了 returnself._session.query(self.model_class).filter(*filter_group).all()
[<common.models_dec_core.Portfolio object at 0x7f2b98157f40>]
也尝试对传递给更新的字典进行硬编码,但得到了同样的错误。
我做错了什么?
我通过将 synchronize_session='fetch' 添加到 更新。真的很想知道为什么需要 - 我有 类似的代码,但不使用变量(模型和列 是硬编码的)并且在没有 synchronize_session.
的情况下也能工作sqlalchemy 1.4.2 不会出现此问题,但 sqlalchemy 1.3.16 会出现此问题。
我认为这是因为默认的 synchronize_session
值是 "evaluate"
并且它无法解决 1.3.16 中的 in_
条件。
以下使用 or_
的条件使用默认值,但使用 in_
的条件需要将 synchronize_session
设置为 "fetch"
。
示例 or_
和 in_
from datetime import datetime, date
from sqlalchemy import (
create_engine,
Text,
Integer,
String,
ForeignKey,
UniqueConstraint,
update,
DateTime,
Date,
Boolean,
LargeBinary,
)
from sqlalchemy.schema import (
Table,
Column,
MetaData,
)
from sqlalchemy.sql import select, and_, or_, func
from sqlalchemy.orm import relationship
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
engine = create_engine("sqlite://", echo=False)
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(100), nullable=False)
code = Column(String(1), nullable=False)
portfolio = Column(String(100), nullable=True)
Base.metadata.create_all(engine)
def update_by_or(session, model_class, **kwargs):
filter_group = []
for col in kwargs['query_params']:
attr = getattr(model_class, col)
filter_group.append(or_(*[attr == v for v in kwargs['query_params'][col]]))
session.query(model_class).\
filter(filter_group[0]).\
update(kwargs['values'])
def update_by_in(session, model_class, **kwargs):
filter_group = []
for col in kwargs['query_params']:
attr = getattr(model_class, col)
filter_group.append(attr.in_(kwargs['query_params'][col]))
session.query(model_class).\
filter(filter_group[0]).\
update(kwargs['values'], synchronize_session='fetch')
def print_users(session):
for u in session.query(User).all():
print (u.id, u.name, u.code, u.portfolio)
session = Session(engine)
session.add(User(name='One', code='A'))
session.add(User(name='Two', code='B'))
session.add(User(name='Three', code='C'))
session.add(User(name='Four', code='D'))
session.commit()
print_users(session)
update_by_in(session, User, **{'query_params': {'code': ['A', 'B', 'C']},
'values': {User.portfolio: 'test1'}})
session.commit()
print_users(session)
update_by_in(session, User, **{'query_params': {'code': ['A', 'B', 'C']},
'values': {User.portfolio: 'test2'}})
session.commit()
print_users(session)
输出
1 One A None
2 Two B None
3 Three C None
4 Four D None
1 One A test1
2 Two B test1
3 Three C test1
4 Four D None
1 One A test2
2 Two B test2
3 Three C test2
4 Four D None
虽然我收到的异常是:
sqlalchemy.exc.InvalidRequestError: Could not evaluate current criteria in Python: "Cannot evaluate clauselist with operator <function comma_op at 0x7f7c082821e0>". Specify 'fetch' or False for the synchronize_session parameter.