web-dev-qa-db-fra.com

possible de filtrer la requête après avoir interrogé? Django

Désolé si la question semble bizarre. Je me demande simplement s'il est possible de créer un nouveau queryset alors que j'ai déjà un queryset.

Par exemple ici ...

 everyone = User.objects.filter(is_active=True)  # this would of course return all users that's active
 not_deleted = User.objects.filter(is_active=True, is_deleted=False)  # return user that's active and not deleted
 is_deleted = User.objects.filter(is_active=True, is_deleted=True)  # return user that's active and is already deleted

Quelle est ma question ... pour not_deleted et is_deleted dont les deux sont actifs est vrai avec est identique à everyone existe-t-il un moyen possible d'utiliser everyone et de filtrer en quelque sorte is_deleted=True ou is_deleted=False? Alors je pense que l'interrogation serait plus rapide et meilleure si c'était possible, n'est-ce pas?

Les trois variables everyone, not_deleted et is_deleted seront alors utilisées pour autre chose.

J'espère que ma question est claire.

Merci d'avance.

8
Dora

Oui, vous pouvez réutiliser des ensembles de requêtes existants.

everyone = User.objects.filter(is_active=True)
active_not_deleted = everyone.filter(is_deleted=False)
active_is_deleted = everyone.filter(is_deleted=True)

Cela ne permet pas d'accélérer les choses, mais ce bloc de code n'exécutera même pas de requête sur la base de données, car les QuangoSets de Django sont évalués paresseusement. Ce que je veux dire, c'est qu'il n'enverra pas la requête à la base de données tant que vous n'avez pas réellement besoin des valeurs. Voici un exemple qui va parler à la base de données.

everyone = User.objects.filter(is_active=True)  # Building SQL...
active_not_deleted = everyone.filter(is_deleted=False)  # Building SQL...
active_is_deleted = everyone.filter(is_deleted=True)  # Building SQL...

# Example of the whole queryset being evaluated
for user in everyone:
    # This will execute the query against the database to return the list of users
    # i.e. "select * from user where is_active is True;"
    print(user)

# Example of using iterator to evaluate one object at a time from the queryset.
for user in active_not_deleted.iterator():
    # This will execute the query for each result, so it doesn't
    # load everything at once and it doesn't cache the results.
    # "select * from user where is_active is True and is_deleted is False limit 1 offset 0;"
    # The offset is incremented on each loop and another query is sent to retrieve the next user in the list.
    print(user)

Recommander la lecture:

En complément de cette réponse, vous pouvez effectuer une requête unique, puis filtrer en Python si vous le souhaitez vraiment. Notez que vous ne pouvez pas effectuer de filtrage ultérieur sur les listes car elles ne sont pas des QuerySets.

everyone = User.objects.filter(is_active=True)
active_not_deleted = list(filter(lambda user: user.is_deleted is False), list(everyone))
active_is_deleted = list(filter(lambda user: user.is_deleted is True), list(everyone))

Dans ce dernier exemple, everyone est un queryset et active_not_deleted et active_is_deleted sont des listes Python d'objets User. Le __set de requête everyone ne sera évalué qu'une seule fois lors du premier appel list(everyone), puis les résultats seront mis en cache.

11
A. J. Parr

Vous pouvez filtrer le nombre de requêtes souhaité autant de fois que vous le souhaitez, car filter() renvoie un nouveau jeu de requêtes. Ainsi, après filtrage, vous obtenez un filtre filtré et vous pouvez filtrer ou orderby et une autre méthode qui renvoie de nouveaux ensembles de requêtes

Donc, vous pouvez faire ceci:

active = User.objects.filter(active=True)
deleted = active.filter(is_deleted=True)
not_deleted = active.filter(is_deleted=False)

Tout cela parce que User.objects - est Queryset et User.objects.filter retournent également Queryset. 

0
Vladyslav

Le mieux que vous puissiez faire est:

active_users = User.objects.filter(active=True)
not_deleted = active_users.filter(is_deleted=False)
deleted = active_users.filter(is_deleted=True)

Donc, la réponse à votre question peut être oui, si je comprends bien.

0
Cory Madden