[Django]-How merge two querysets from same model without ordering them

4👍

You should use the union(…) [Django-doc] function here, like:

queryset = modelA.objects.filter(id=modelB.rel_id).union(
    modelA.objects.exclude(id=modelB.rel_id),
    all=True
)

The or | [Django-doc] on the other hand will, as the documentation says:

Combines two QuerySets using the SQL OR operator.

The following are equivalent:

Model.objects.filter(x=1) | Model.objects.filter(y=2)
from django.db.models import Q
Model.objects.filter(Q(x=1) | Q(y=2))

That being said, if you want to specify the modelB.rel_id as last, you can do that as follows:

from django.db.models import BooleanField, ExpressionWrapper, Q

modelA.objects.annotate(
    rel_to_b=ExpressionWrapper(
        Q(id=modelB.rel_id),
        output_field=BooleanField()
    )
).order_by('rel_to_b')

Here we thus annotate the ModelAs with an extra attribute rel_to_b, in case the objects are related to B, that attribute will be True, and since True is ordered later than False, that will be the last row.

This will produce a query that looks like:

SELECT model_a.*,
       model_a.id = modelB.rel_id AS rel_to_b
FROM model_a
ORDER BY rel_to_b ASC

Leave a comment