【问题标题】:Django - Is there a way to optimize ORM ManyToOne calls in a loop?Django - 有没有办法在循环中优化 ORM ManyToOne 调用?
【发布时间】:2019-07-02 03:57:45
【问题描述】:

我发现自己在我的 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。

【问题讨论】:

标签: python django django-models django-views django-orm


【解决方案1】:

你有模特吗? 如果是的话,我建议上传模型代码。

我通常这样编码。 首先,如果我使用 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()

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-05
  • 2023-01-09
  • 2021-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多