1
votes

peewee: Comment ajouter une clause where à une sélection?

J'ai des modèles comme celui-ci:

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),
        )

Je voudrais:

  1. (par défaut) capable de sélectionner des lignes avec is_active == True et is_deleted == False

ou

  1. sélectionnez toutes les lignes mais sautez simplement les indicateurs is_active et is_deleted


0 commentaires

3 Réponses :


0
votes

Voici une réponse qui n'est pas particulière à peewee.

Supposons que votre table (sans nom) ci-dessus soit "chose", donc essentiellement votre modèle est bon pour les requêtes comme select * from thing .

Maintenant, définissez une vue associée qui sélectionne certaines choses, sélectionne votre sous-ensemble de lignes préféré:

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

Pointez votre modèle vers que relation, qui se trouve être une vue (une requête nommée) plutôt qu'une table.


0 commentaires

1
votes

C'est juste Python ... ajoutez une méthode d'assistance à votre classe de modèle. Par exemple, si j'ai une classe Post pour les articles de blog, je pourrais écrire:

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

Ensuite, je pourrais avoir une liste de tous les articles publiés:

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

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


1 commentaires

avez-vous une idée comment appliquer cela aux jointures?



0
votes

Je voudrais étendre une excellente réponse coleifer .

Pour les jointures et plus encore complique les requêtes que nous pouvons utiliser PeeWee CTE a > fonctionnalité comme suit:

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

Ensuite, lorsque nous ne voulons que des messages actifs pour les utilisateurs actifs, nous pouvons faire quelque chose comme ceci:

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()
RAPPELEZ-VOUS

L'objet for CTE que vous devez référencer en ajoutant .c. et ajoutez ceci cte à la fin de votre requête en ajoutant .with_cte ()


2 commentaires

Félicitations pour avoir appris le CTE. Cette réponse brouille certainement les eaux et la rend assez déroutante pour quiconque arrive ici via Google. Au lieu de répondre à votre vraie question, vous avez parlé de fonctionnalités plutôt avancées et écrit de nombreuses lignes de choses inutiles pour que quelqu'un doive parcourir pour obtenir la réponse réelle.


@coleifer alors pouvez-vous étendre votre réponse pour fournir une solution plus flexible? Comment créer quelque chose comme View ou Proxy à modéliser lorsque vous souhaitez l'utiliser dans les jointures?