peewee:如何在任何选择中添加where子句?

问题描述 投票:1回答:3

我有这样的模特:

class AbstractBaseModel(peewee.Model):
    uuid = peewee.UUIDField(default=uuid4)
    is_active = peewee.BooleanField(default=False)
    is_deleted = peewee.BooleanField(default=False)
    created_at = peewee.DateTimeField(default=datetime.now)
    updated_at = peewee.DateTimeField(default=datetime.now)
    deleted_at = peewee.DateTimeField(null=True)

    class Meta:
        abstract = True
        indexes = (
            (('is_active', 'is_deleted'), False),
        )

我想要:

  1. (默认情况下)能够使用is_active == Trueis_deleted == False选择行

要么

  1. 选择所有行,但只是跳过is_activeis_deleted标志
python-3.x peewee
3个回答
1
投票

它只是Python ...为模型类添加一个辅助方法。例如,如果我有博客帖子的Post类,我可能会写:

class Post(Model):
    status = IntegerField()  # 1=live, 2=draft, 3=deleted, e.g.

    @classmethod
    def visible(cls):
        return cls.select().where(cls.status == 1)

然后,我可能会有所有已发布帖子的列表视图:

@app.route('/')
def post_index():
    query = Post.visible().order_by(Post.timestamp.desc())
    return render_template('post_index.html', query=query)

0
投票

这是一个不是peewee特有的答案。

假设你上面的(未命名)表是“东西”,所以基本上你的模型擅长select * from thing这样的查询。

现在定义一个相关的视图,挑选出某些东西,挑出你最喜欢的行子集:

sqlite> create view thing_v  as
   ...>   select uuid, created_at, updated_at, deleted_at
   ...>   from thing
   ...>   where is_active == True and is_deleted == False;

将模型指向该关系,该关系恰好是视图(命名查询)而不是表。


0
投票

我想延长伟大的coleifer答案。

对于连接和更复杂的查询,我们可以使用PeeWee CTE功能,如下所示:

class BaseModel(peewee.Model):
    is_deleted = peewee.BooleanField(default=False, index=True)

    @classmethod
    def visible_where_clause(cls):
        return cls.is_deleted == False

    @classmethod
    def visible(cls):
        return cls.select().where(cls.visible_where_clause())

    @classmethod
    def cte(cls, name=None):
        if name is None:
            name = 'CTE_{}'.format(cls.__name__)
        return cls.visible().cte(name)

    class Meta:
        abstract = True

class User(BaseModel):
    username = peewee.CharField(max_length=255, unique=True)
    is_active = peewee.BooleanField(default=True, index=True)

    @classmethod
    def visible_where_clause(cls):
        return (
            (super().visible_where_clause()) & (cls.is_active == True)
        )

UserCTE = User.cte()


class Post(BaseModel):
    status = peewee.IntegerField()  # 1=live, 2=draft, 3=deleted, e.g.
    user = peewee.ForeignKeyField(User)
    title = peewee.CharField(max_length=255)

    @classmethod
    def visible_where_clause(cls):
        return (
                (super().visible_where_clause()) & (cls.status == 1)
        )

PostCTE = Post.cte()

然后,当我们只想要活跃用户的活动帖子时,我们可以这样做:

posts = (
    Post
    .visible()
    .select(Post.title)
    .join(UserCTE, on=Post.user == UserCTE.c.id)
    .with_cte(UserCTE)
)
for post in posts:
    print(post.title)

记得

您必须通过添加CTE来引用.c.<column_name>对象,并通过添加cte在查询结尾添加此.with_cte(<list of all used CTEs>)

© www.soinside.com 2019 - 2024. All rights reserved.