首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >sqlalchemy hybrid_property和表达式

sqlalchemy hybrid_property和表达式
EN

Stack Overflow用户
提问于 2017-08-04 00:17:50
回答 1查看 597关注 0票数 0

我不能理解这些表达。如何让以下代码正常工作?

代码语言:javascript
复制
class OperationType(Enum):
    MINUS = 1
    MINUS_CORR = 2
    PLUS = 3
    PLUS_CORR = 4

按类型分组操作

代码语言:javascript
复制
BALANCE_PLUS_OPERATIONS = [
    OperationType.PLUS.value,
    OperationType.PLUS_CORR.value
]

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

运营模式

代码语言:javascript
复制
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)

用户模型

代码语言:javascript
复制
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')

表达式是错误的,并且将产生错误的结果:

代码语言:javascript
复制
users = User.query.filter_by(balance=51).all()
for u in users:
    print(u, u.balance)

打印:

代码语言:javascript
复制
<User(foo@bar.com)> 51
<User(bar@foor.com)> 0

但我只期望有一条记录:

代码语言:javascript
复制
<User(foo@bar.com)> 51

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-08-04 01:03:34

我将从上下文中假设这些方法属于User类。在这样的光芒下

代码语言:javascript
复制
.where(User.id == cls.id) \

是有效的

代码语言:javascript
复制
.where(User.id == User.id) \

或者仅仅是where(True),所以每个用户都会加入到每个操作中,而这可能意味着像这样

代码语言:javascript
复制
.where(Operation.user_id == cls.id) \

虽然由于缺乏实例而不能说。如果确实发生了不正确的联接,它解释了查询返回另一个用户的原因:它是通过属于正确用户的操作联接的。

您可能还需要添加

代码语言:javascript
复制
.correlate(cls) \

as_scalar()之前。我认为最外层的select也是多余的。你应该能够

代码语言:javascript
复制
return (p - m).label('BALANCE')
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45489650

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档