假设以下设置:
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class MyClass(Base):
id = Column(Integer, primary_key=True)
name = Column(String)
使用SQLAlchemy查询数据库的正常范例是执行以下操作:
Session = sessionmaker()
engine = 'some_db_location_string'
session = Session(bind=engine)
session.query(MyClass).filter(MyClass.id == 1).first()
假设,我想将查询简化为以下内容:
MyClass(s).filter(MyClass.id == 1).first()
OR MyClass(s).filter(id == 1).first()
我该怎么做?我第一次尝试使用模型Mixin类失败了。这就是我试过的:
class ModelMixins(object)
def __init__(self, session):
self.session = session
def filter(self, *args):
self.session.query(self).filter(*args)
# Redefine MyClass to use the above class
class MyClass(ModelMixins, Base):
id = Column(Integer, primary_key=True)
name = Column(String)
主要的失败似乎是我无法完全转移表达式' MyClass.id == 1'到作为会话对象一部分的实际过滤函数。
人们可能会问我为什么要这样做:
MyClass(s).filter(id == 1).first()
我已经看过类似之前使用的类似内容,并且认为语法变得如此清晰,我可以实现这一点。我想复制这个,但一直没能。能够做这样的事情:
def get_stuff(some_id):
with session_scope() as s:
rec = MyClass(s).filter(MyClass.id== some_id').first()
if rec:
return rec.name
else:
return None
......似乎是最干净的做事方式。首先,会话管理是分开的。其次,查询本身被简化了。拥有这样的Mixin类可以让我将过滤器功能添加到任意数量的类中......那么有人可以在这方面提供帮助吗?
答案 0 :(得分:1)
Integer
需要类;你给它session.query
,这是一个实例。将您的self
方法替换为:
filter
并且至少有这么多:
def filter(self, *args):
return session.query(self.__class__).filter(*args)
生成的SQL看起来也正确(为清晰起见添加了换行符):
In [45]: MyClass(session).filter(MyClass.id==1)
Out[45]: <sqlalchemy.orm.query.Query at 0x10e0bbe80>
不保证不会有奇怪之处;我以前从未尝试过这样的事情。
答案 1 :(得分:0)
我一直在使用此mixin获得成功。很可能不是世界上最有效的事情,我也不是专家。我为每个表定义一个date_created
列
class QueryBuilder:
"""
This class describes a query builer.
"""
q_debug = False
def query_from_dict(self, db_session: Session, **q_params: dict):
"""
Creates a query.
:param db_session: The database session
:type db_session: Session
:param q_params: The quarter parameters
:type q_params: dictionary
"""
q_base = db_session.query(type(self))
for param, value in q_params.items():
if param == 'start_date':
q_base = q_base.filter(
type(self).__dict__.get('date_created') >= value
)
elif param == 'end_date':
q_base = q_base.filter(
type(self).__dict__.get('date_created') <= value
)
elif 'like' in param:
param = param.replace('_like', '')
member = type(self).__dict__.get(param)
if member:
q_base = q_base.filter(member.ilike(f'%{value}%'))
else:
q_base = q_base.filter(
type(self).__dict__.get(param) == value
)
if self.q_debug:
print(q_base)
return q_base