web-dev-qa-db-fra.com

Comment ajouter une instance de modèle à un ensemble de requêtes Django?

Il semble qu’un jeu de requêtes Django se comporte d’une manière ou d’une autre comme une liste python.

Mais il ne supporte pas la méthode .append () de la liste, comme je le sais.

Ce que je veux faire, c'est comme:

from my_Django_app.models import MyModel

queryset = MyModel.objects.none()
queryset.append(MyModel.objects.first())      ## no list's .append() method!

Est-il possible d'ajouter une instance de modèle à un ensemble de requêtes existant?

12
June

Vous pouvez également utiliser l'opérateur | pour créer une union:

queryset = MyModel.objects.none()
instance = MyModel.objects.first()
queryset |= MyModel.objects.filter(pk=instance.pk)

Mais sachez que cela générera différentes requêtes en fonction du nombre d'éléments que vous ajoutez de cette façon, ce qui rend la mise en cache des requêtes compilées inefficace.

7
Feuermurmel

Non, un ensemble de requêtes est une représentation d'une requête - d'où son nom, et non d'une collection arbitraire d'instances.

Si vous avez réellement besoin d'un ensemble de requêtes réel plutôt que d'une liste, vous pouvez essayer de cumuler les ID des objets dont vous avez besoin, puis de les obtenir via une requête __in:

list_of_ids = []
list_of_ids.append(my_id)
...
queryset = MyModel.objects.filter(id__in=list_of_ids)

Ce n'est pas très efficace, cependant.

11
Daniel Roseman

Cela peut être fait en utilisant union. Après cela, le type du résultat peut être vu comme <class 'Django.db.models.query.QuerySet'>. Ainsi, deux ensembles de requêtes peuvent être combinés. Voyons un exemple.

query1 = User.objects.filter(is_active=True)

query2 = User.objects.filter(is_active=False)

combined_query = query1.union(query2)

print (type(combined_query))

Le programme ci-dessus affichera le résultat comme ci-dessous, confirmant qu'il s'agit d'un interrogation

<class 'Django.db.models.query.QuerySet'>

Donc, fondamentalement, Django exécute la requête ci-dessous pour l’union.

(SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."is_active" = True) 
UNION 
(SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login", "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name", "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."is_active" = False)

Cela signifie également qu'il y aura une erreur (Django.db.utils.ProgrammingError: each UNION query must have the same number of columns) si l'union est tentée avec deux tables différentes.

1
SuperNova

Queryset n'est pas une list

Alors

to_list = queryset.values()

Pour combiner queryset

from itertools import chain
result_queryset = list(chain(queryset1, queryset2))

ou

querysets = [queryset1, queryset2]
result_queryset = list(chain(*querysets))
1
itzMEonTV