Reputation: 1261
Using Django 1.8
I'm trying to get a queryset through the backward foreign key relationship where there is only one distinct value of one the fields in the source models.
class Franchise(models.Model):
...
class Title(models.Model):
franchise = models.ForeignKey(Franchise, related_name='titles')
genre = models.CharField(max_length=20)
...
So in this example I would like to get a queryset of Franchise objects of which all Titles have the same genre. I can add methods to the Franchise model and generate a list of franchise id's obtain a queryset, but this is very slow.
class Franchise(models.Model):
...
def get_title_genres(self):
self.titles.values_list('genre', flat=True).distinct()
def is_single_genre(self):
return len(self.get_title_genres()) == 1
franchise_ids = [
franchise.id
for franchise in Franchise.objects.all()
if franchise.is_single_genre()
]
queryset = Franchise.objects.filter(id__in=franchise_ids)
Is there a more efficient way I can do this?
Upvotes: 1
Views: 148
Reputation: 308899
Unless you need a queryset, you don't need to the second queryset with id__in=franchise_ids
.
franchises = [
franchise for franchise in Franchise.objects.all()
if franchise.is_single_genre()
]
You could use prefetch_related
to fetch all of the related titles with the queryset, however you won't be able to reuse the get_title_genres
method, because the values_list(...).distinct()
would trigger a new SQL query.
franchises = [
franchise for franchise in Franchise.objects.prefetch_related('titles')
if len(set(t.genre for t in franchise.titles)) == 1
]
Upvotes: 1