https://github.com/django/django/pull/13038
Above pull request (Ticket #24141) has a discussion on how to handle qs.contains() for QuerySets with qs.values() or qs.values_list() calls.
Current patch checks self._result_cache if exists and iterable class is ModelIterable, otherwise returns .filter(pk=
obj.pk).exists(), i.e. hitting the database.
These are the options I see:
1. As above.
2. Throw an exception if iterable class is not ModelIterable (when using .values or .values_list).
3. Accept dict lookup for .values and tuple lookup for .values_list querysets, so that the .contains() query matches what you get from the iterable.
It seems kind of neat to be able to check if an object is in a QuerySet, even if you group that QuerySet using .values('group').annotate(sum=Sum('value')).order_by(). But that was never the case I saw for QuerySet.contains(), so I have no real preference here.
Johan