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 ModelA
s 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
Source:stackexchange.com