Peewee原子更新复杂逻辑

时间:2018-07-23 07:12:59

标签: python python-3.x atomic peewee

我需要更新整个用户表的字段。 docs中指出,我不应该遍历所有表记录。但是要计算新的字段值,我需要使用循环,用户关系以及其他依赖于具体模型的复杂逻辑来进行计算。

我试图将此计算包括在模型的属性中,但是我得到了:

peewee.InterfaceError: Error binding parameter 0 - probably unsupported type.

原子更新:

    query = User.update(balance=(User.balance + User.partners_reward))\
    .where(User.deposit >= 3)

型号:

class User(peewee.Model):
    deposit = peewee.DecimalField(default=0)
    balance = peewee.DecimalField(default=0)

    @property
    def partners(self):
        query = (
            User.select(User, Partnership)
                .join(Partnership, JOIN.INNER, on=Partnership.invited)
                .where(Partnership.referral == self.id)
        )
        partners = query.execute()
        return partners


    @property
    def partners_reward(self):
        partners = self.partners
        sum_reward = 0
        partner_reward = 0.02

        for partner in partners:
            reward = partner.deposit * partner_reward
            sum_reward += reward

        return sum_reward

道具说明:

每个用户都有合作伙伴(他邀请的其他用户),并根据他们获得奖励。因此,要完成更新,我需要使用关系收集用户合作伙伴,然后使用循环来计算实际的奖励。

将属性更改为方法可以解决此问题,但是我不知道如何访问具体的用户实例。

那么如何在原子更新中实现一些复杂的逻辑,还是应该不建议使用循环来实现?

1 个答案:

答案 0 :(得分:1)

您可以使用子查询。如果我正确理解您的查询示例,那只是每个合作伙伴存款的总和* .02?

subq = (Partnership
        .select(fn.COALESCE(fn.SUM(Partnership.deposit * .02)))
        .where(Partnership.referral == User.id))
res = (User
       .update(reward=subq)
       .execute())

上述查询的作用是,对于每个用户,它选择与该用户关联的所有伙伴关系行,并对伙伴关系存款* .02求和,并将结果存储在用户的“奖励”列中(假设存在该列) )。 “ COALESCE()”位用于处理用户没有伙伴的情况,以便返回0而不是null。

如果您希望增加用户的余额,则:

subq = (Partnership
        .select(fn.COALESCE(fn.SUM(Partnership.deposit * .02)))
        .where(Partnership.referral == User.id))
res = (User
       .update(balance=User.balance + subq)
       .execute())