Reputation: 93
I'm trying to filter a queryset by checking that the object is in a list of those objects.
employee_list = [<Employee: A>, <Employee: B>, <Employee: C>]
qs = Employee.objects.filter(id__in=employee_list, [other_filters])
After running above, qs is an empty list. I was thinking that I could make a new list such as
employee_ids = [emp.id for emp in employee_list]
qs = Employee.objects.filter(id__in=employee_ids, [other_filters])
I haven't done benchmarking on this method, but I imagine performance would probably take a hit. Alternatively I could intersect the lists afterwards like:
qs = Employee.objects.filter([other_filters])
filtered_qs = [emp for emp in employee_lids if emp in qs]
However, I think the performance hit would be even worse this way.
What's the best/fastest way to do this? Thanks.
Upvotes: 1
Views: 3097
Reputation: 2422
As Martol1ni noted you want to filter at the SQL level whenever possible so I think your methods do get progressively slower, but another issue...
Based on the Django Docs: https://docs.djangoproject.com/en/dev/ref/models/querysets/ I think yourid__in
should be a list of integer ids, not a list of models.
Edit: Oh I see he covered this in his answer, but it was not explicit that it was incorrect in your question.
Edit2:
But yes, if you want to know for sure, what really matters is real world performance, which you can do with django-debug-toolbar. It seems to me though the real issue was the id__in
misuse which lead you to find trickier ways to do what you wanted to do.
Upvotes: 1
Reputation: 4702
Rule of thumb is to filter as much as possible through SQL, so I would go for
qs = Employee.objects.filter(id__in=[emp.id for emp in employee_list], [other_filters])
I do not have any performance testing to back this up with though.
Upvotes: 2