[英]sqlalchemy hybrid_property and expression
I can not understand the expressions. 我不明白这些表达。 How to get the following code to work?
如何使以下代码正常工作?
class OperationType(Enum):
MINUS = 1
MINUS_CORR = 2
PLUS = 3
PLUS_CORR = 4
group operation by type 按类型分组操作
BALANCE_PLUS_OPERATIONS = [
OperationType.PLUS.value,
OperationType.PLUS_CORR.value
]
BALANCE_MINUS_OPERATIONS = [
OperationType.MINUS.value,
OperationType.MINUS_CORR.value
]
Operation model 运作模式
class Operation(Model):
__tablename__ = 'operation'
id = db.Column(db.BigInteger, primary_key=True)
created_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow)
operation_type = db.Column(db.SmallInteger, nullable=False)
amount = Column(db.Integer, nullable=False)
user_id = db.Column(db.ForeignKey('users.id'), nullable=False)
user = relationship('User', backref='operation', uselist=False)
User model 用户模型
class User(UserMixin, Model):
__tablename__ = 'users'
id = Column(db.Integer, primary_key=True)
operations = relationship("Operation", backref="users")
@hybrid_property
def balance(self):
plus = sum(op.amount for op in self.operations if op.operation_type in BALANCE_PLUS_OPERATIONS)
minus = sum(op.amount for op in self.operations if op.operation_type in BALANCE_MINUS_OPERATIONS)
return plus - minus
@balance.expression
def balance(cls):
p = select([func.sum(Operation.amount).label('BALANCE_PLUS_OPERATIONS')]) \
.where(Operation.operation_type.in_(BALANCE_PLUS_OPERATIONS)) \
.where(User.id == cls.id) \
.as_scalar()
m = select([func.sum(Operation.amount).label('BALANCE_MINUS_OPERATIONS')]) \
.where(Operation.operation_type.in_(BALANCE_MINUS_OPERATIONS)) \
.where(User.id == cls.id) \
.as_scalar()
return select([p - m]).label('BALANCE')
The expression is wrong and will produce the wrong result: 表达式错误,将产生错误的结果:
users = User.query.filter_by(balance=51).all()
for u in users:
print(u, u.balance)
print: 打印:
<User(foo@bar.com)> 51
<User(bar@foor.com)> 0
but i expected only one record: 但我只希望有一个记录:
<User(foo@bar.com)> 51
Thanks 谢谢
I'll assume from context that the methods belong to the User
class. 我将根据上下文假设这些方法属于
User
类。 In that light 鉴于此
.where(User.id == cls.id) \
is effectively 有效地
.where(User.id == User.id) \
or just where(True)
, and so every user is joined with every operation, when it probably is meant to be something like 或
where(True)
,因此每个用户都可以进行每个操作,而这可能意味着
.where(Operation.user_id == cls.id) \
though impossible to say due to lacking example. 尽管由于缺乏示例而无法说。 If the incorrect join does happen, it explains why the other user is returned by the query: it was joined with operations belonging to the correct user.
如果确实发生了不正确的联接,它说明了查询返回其他用户的原因:该联接是通过属于正确用户的操作进行联接的。
You also might have to add 您可能还需要添加
.correlate(cls) \
before as_scalar()
. 在
as_scalar()
之前。 The outermost select is also redundant, I think. 我认为最外面的选择也是多余的。 You should be able to just
您应该能够
return (p - m).label('BALANCE')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.