How to add an model instance to a django queryset?

PythonDjango

Python Problem Overview


It seems like a django queryset behaves somehow like a python list.

But it doesn't support list's .append() method as I know.

What I want to do is like:

from my_django_app.models import MyModel

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

Is there any way to add an model instance to an existing queryset?

Python Solutions


Solution 1 - Python

You can also use the | operator to create a union:

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

But be warned that this will generate different queries depending on the number of items you append this way, making caching of compiled queries inefficient.

Solution 2 - Python

No. A queryset is a representation of a query - hence the name - not an arbitrary collection of instances.

If you really need an actual queryset rather than a list, you could try accumulating the IDs of the objects you need and then getting the objects via an __in query:

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

This isn't very efficient, though.

Solution 3 - Python

This can be done using union. After doing this, the type of the result can be seen as <class 'django.db.models.query.QuerySet'>. So two querysets can be combined. Lets see an example.

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

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

combined_query = query1.union(query2)

print (type(combined_query))

The above program will print result as below, confirming it is a queryset

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

So basically Django executes the below query for 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)

This also means that there will be error(django.db.utils.ProgrammingError: each UNION query must have the same number of columns) if union is tried with two different tables.

Solution 4 - Python

Queryset is not a list

So

to_list = queryset.values()

To combine queryset

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

or

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJuneView Question on Stackoverflow
Solution 1 - PythonFeuermurmelView Answer on Stackoverflow
Solution 2 - PythonDaniel RosemanView Answer on Stackoverflow
Solution 3 - PythonSuperNovaView Answer on Stackoverflow
Solution 4 - PythonitzMEonTVView Answer on Stackoverflow