How to add an model instance to a django queryset?
Question:
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?
Answers:
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))
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.
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.
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.
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?
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))
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.
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.
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.