Reputation: 17869
So I am making a query that starts as the following:
queryset = FooBar.objects.filter(example__pk__lt=50)
where example
is a foreign key. So this will get all FooBar
objects that are connected to one of the first fifty Example
s. But here is my goal:
I want to have this queryset only include FooBar
objects where a different field, lets say target
, is not distinct.
I can do that with the following loop:
target_ids = [] #holding a check list for comparison
correct_targets = [] #holding the objects I want to have
for item in queryset: #iteration
target_ids.append(item.example.pk) #send primary key to check list
if target_ids.count(item.example.pk) == 2: #check if there has been more than one (if there is more than two I don't send another correct target since I would have already sent it previously)
correct_targets.append(item) #send correct target
I was hoping that there would be a way to get a queryset of these objects from my queryset
without having to loop through. Is this possible?
Upvotes: 2
Views: 2809
Reputation: 967
Just annotate on any non-dictinct field value
from your FK
model:
from django.db.models import F
....
qs = FooBar.objects.filter(example__pk__lt=50).annotate(example_target=F(example__target))
This query will contain duplicated FooBar
objects, one object for each new target
value.
Upvotes: 0
Reputation: 134731
It's possible, using filtering on annotation.
from django.db.models import Count
qs = FooBar.objects.filter(example__pk__lt=50)
qs = qs.annotate(num_examples=Count('example')).filter(num_examples__gt=1)
Upvotes: 4
Reputation: 2776
You could use an aggregate query to get the list of nondistinct items and then use that to filter your other query.
nondistinct = Example.objects.values('target').annotate(Count('id')).filter(id__count__gt=1)
Foobar.objects.filter(example__pk__lt=50).filter(example__target__in=[item['target'] for item in nondistinct])
Upvotes: 1
Reputation: 83706
I am not sure if "reverse distinct" is possible with Django ORM, or not even underlying SQL database.
However the following might be possible
Query all items to queryset q1
Query distict items to queryset q2
Take the difference qs_not_distict = qs1.exclude(pk__in=qs2)
Upvotes: 0