eugene
eugene

Reputation: 41745

Django, avoid N+1 query

I have three models in play, and want to avoid N+1 query.

class Rule(models.Model):

    pass


class RuleConstraint(models.Model):

    rules = models.ManyToManyField(Rule)


class Foo(models.Model):

    rule = models.ForeignKey(Rule, related_name='foos')

for a given foo, I can get related RuleConstraints like the following

RuleContraint.objects.filter(rules__foos=foo)

Question is, how do I avoid N+1 query symptom, when I have foos instead of a single foo.

ie, is there a better way of doing than

for foo in foos:
  rule_constraints = RuleConstraint.objects.filter(rules__foos=foo)

Upvotes: 0

Views: 946

Answers (1)

Alasdair
Alasdair

Reputation: 309089

You want prefetch_related

foos = Foo.objects.prefetch_related('rule__rule_constraint')

You can then iterate through the queryset with:

for foo in foos:
    rule_constraints = foo.rule.ruleconstraint_set.all()

You can improve this further by using select_related to fetch the rule.

foos = Foo.objects.select_related('rule').prefetch_related('rule__rule_constraint')

For more information see the prefetch related docs - your models are very similar to those in the examples.

Upvotes: 1

Related Questions