Temirulan
Temirulan

Reputation: 53

How I can write only one django orm query?

The goal is to filter Fitness objects by specified SportType objects, i.e. all Fitness objects which contains at least one specified SportType object as foreignkey.

Here is my models and example:

class Fitness(models.Model):
  name = models.Charfield(max_length=100)

class SportType(models.Model):
  name = models.CharField(max_length=100)

class FitnessSportType(models.Model):
  fitness = models.ForeignKey(Fitness, related_name='sport_type_set')
  sport_type = models.ForeignKey(SportType, related_name='fitness_set')

f1 = Fitness.objects.create(name='foo')
f2 = Fitness.objects.create(name='bar')
f3 = Fitness.objects.create(name='goo')
s1 = SportType.objects.create(name='a')
s2 = SportType.objects.create(name='b')
s3 = SportType.objects.create(name='c')
FitnessSportType.objects.create(fitness=f1, sport_type=s1)
FitnessSportType.objects.create(fitness=f1, sport_type=s2)
FitnessSportType.objects.create(fitness=f2, sport_type=s1)
FitnessSportType.objects.create(fitness=f2, sport_type=s3)
FitnessSportType.objects.create(fitness=f3, sport_type=s2)
SOME_MAGIC_FUNCTION([s1, s3]) = [f1, f2]

P.S: sorry for bad English :)

Upvotes: 1

Views: 48

Answers (3)

Daniel Roseman
Daniel Roseman

Reputation: 599956

You can improve this query by explicitly declaring FitnessSportType as the through table in the many-to-many relationship between Fitness and SportType:

class Fitness(models.Model):
    ...
    sport_types = models.ManyToManyField('SportType', through='Fitness')

Now you can do:

Fitness.objects.filter(sport_types__in=[s1, s2])

If you don't have any other fields on FitnessSportType, there's no reason to declare it explicitly at all; remove it, and the through attribute on the M2M, and the query will work exactly the same.

Upvotes: 2

azundo
azundo

Reputation: 6052

You can use double underscores to traverse relationships and __in to test for multiple SportTypes.

results = Fitness.objects.filter(sport_type_set__sport_type__in=[s1, s2])

Upvotes: 2

shafikshaon
shafikshaon

Reputation: 6404

Try this

FitnessSportType.objects.filter(sport_type='a').values('fitness__name')

You will get all fittness name which sport_type equal to a

Upvotes: 1

Related Questions