2017-08-03 162 views
0

我无法理解表达式。如何让下面的代码工作?按类型sqlalchemy hybrid_property和表达式

class OperationType(Enum): 
    MINUS = 1 
    MINUS_CORR = 2 
    PLUS = 3 
    PLUS_CORR = 4 

组操作

BALANCE_PLUS_OPERATIONS = [ 
    OperationType.PLUS.value, 
    OperationType.PLUS_CORR.value 
] 

BALANCE_MINUS_OPERATIONS = [ 
    OperationType.MINUS.value, 
    OperationType.MINUS_CORR.value 
] 

操作模型

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) 

用户模型

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') 

表达是错误的,会产生错误的结果:

users = User.query.filter_by(balance=51).all() 
for u in users: 
    print(u, u.balance) 

打印:

<User([email protected])> 51 
<User([email protected])> 0 

,但我预计只有一条记录:

<User([email protected])> 51 

感谢

+0

请编辑您的问题解释(1)您预期发生,(2)你得到了什么错误(或者怎样的结果不同)和(3)缩小问题直到只是有问题的代码。阅读[如何创建最小,完整和可验证示例](https://stackoverflow.com/help/mcve)将有所帮助。 – HFBrowning

+0

谢谢。更正 – 13akaEagle

回答

1

我会从上下文中假设的方法都属于User类。有鉴于此

.where(User.id == cls.id) \ 

实际上是

.where(User.id == User.id) \ 

或只是where(True),所以每个用户都加入了与每一个操作,当它可能意味着是像

.where(Operation.user_id == cls.id) \ 

虽然由于缺乏实例而不能说。如果不正确的连接发生,它解释了查询返回其他用户的原因:它与属于正确用户的操作连接。

您还可能有as_scalar()之前添加

.correlate(cls) \ 

。我想,最外层的选择也是多余的。你应该能够公正

return (p - m).label('BALANCE') 
+0

非常感谢!我需要的。一个网站没有发布全部代码。基本用户和操作中有两个表。用户有很多操作。 – 13akaEagle