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

しかし、私は1つのレコードのみ予想:

<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

多くの感謝!何が必要なの?サイトがすべてのコードを公開することはありませんでした。基本UserとOperationに2つのテーブルがあります。ユーザーには多くの操作があります。 – 13akaEagle

関連する問題