Django - 有没有办法在循环中优化 ORM ManyToOne 调用?
Django - Is there a way to optimize ORM ManyToOne calls in a loop?
我发现自己在我的 Django 视图中有这种模式:
<ol>
{% for a in ModelA %}
<li>{{ a.title }}</li>
<ol>
{% for b in a.modelb_set.all %}
<li>{{ b.title }}</li>
<ul>
{% for c in b.modelc_set.all %}
<li>{{ c.text }}</li>
<ul>
{% for d in c.modeld_set.all %}
<li>{{ d.text }}</li>
{% endfor %}
</ul>
{% endfor %}
{% endif %}
</ul>
{% endfor %}
</ol>
{% endfor %}
</ol>
这里的问题当然是这是在进行 n^4 次数据库调用,这是非常不可扩展的。对于单个 ModelA
对象,我进行了大约 23 个 SQL 查询,并且我认为这个数字只会随着 ModelA
查询数量的增加而增加。
有没有一种通用的方法可以减少此处需要进行的查询数量?任何想法将不胜感激:)
(如果你很好奇,实际代码是 here - ModelA 是 Poll,ModelB 是 TextChoiceQuestion,ModelC 是 TextChoice,ModelD 是 TextChoiceNuance。
你有模型吗?
如果是这样,我建议上传模型代码。
我通常这样编码。
首先,如果我使用 ManyToManyField,请使用 prefetch_related('fields', 'field__subfield', ).
Model.objects.prefetch_related('afield', 'afield__bmodel_field', 'afield__bmodel_field__cmodel_field')
其次,你必须使用related_name。不管ManyToManyField,ForeignKey,都可以取一个相关性更好的名字。
class CheckList(models.Model):
"""docstring for CheckList"""
""" 설명 """
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class Question(models.Model):
checklist = models.ForeignKey(CheckList,
on_delete=models.CASCADE, related_name='questions')
# example
check_list = CheckList.objects.prefetch_related('questions').all()
我发现自己在我的 Django 视图中有这种模式:
<ol>
{% for a in ModelA %}
<li>{{ a.title }}</li>
<ol>
{% for b in a.modelb_set.all %}
<li>{{ b.title }}</li>
<ul>
{% for c in b.modelc_set.all %}
<li>{{ c.text }}</li>
<ul>
{% for d in c.modeld_set.all %}
<li>{{ d.text }}</li>
{% endfor %}
</ul>
{% endfor %}
{% endif %}
</ul>
{% endfor %}
</ol>
{% endfor %}
</ol>
这里的问题当然是这是在进行 n^4 次数据库调用,这是非常不可扩展的。对于单个 ModelA
对象,我进行了大约 23 个 SQL 查询,并且我认为这个数字只会随着 ModelA
查询数量的增加而增加。
有没有一种通用的方法可以减少此处需要进行的查询数量?任何想法将不胜感激:)
(如果你很好奇,实际代码是 here - ModelA 是 Poll,ModelB 是 TextChoiceQuestion,ModelC 是 TextChoice,ModelD 是 TextChoiceNuance。
你有模型吗? 如果是这样,我建议上传模型代码。
我通常这样编码。 首先,如果我使用 ManyToManyField,请使用 prefetch_related('fields', 'field__subfield', ).
Model.objects.prefetch_related('afield', 'afield__bmodel_field', 'afield__bmodel_field__cmodel_field')
其次,你必须使用related_name。不管ManyToManyField,ForeignKey,都可以取一个相关性更好的名字。
class CheckList(models.Model):
"""docstring for CheckList"""
""" 설명 """
name = models.CharField(max_length=30)
def __str__(self):
return self.name
class Question(models.Model):
checklist = models.ForeignKey(CheckList,
on_delete=models.CASCADE, related_name='questions')
# example
check_list = CheckList.objects.prefetch_related('questions').all()