2017-08-03 167 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