Django - Есть ли способ оптимизировать вызовы ORM ManyToOne в цикле? - PullRequest
0 голосов
/ 08 февраля 2019

Я вижу, что в моих представлениях 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.

Есть ли общий способ снизить количество запросов, которые необходимо сделать здесь?Любые идеи будут оценены:)

(Если вам интересно, фактический код здесь - ModelA - это опрос, ModelB - это TextChoiceQuestion, ModelC - это TextChoice, а ModelD - это TextChoiceNuance.

1 Ответ

0 голосов
/ 08 февраля 2019

У вас есть модель?Если это так, я рекомендую загрузить код модели.

Я обычно так кодирую.Во-первых, если я использую ManyToManyField, используйте prefetch_related ('fields', 'field__subfield',).

Model.objects.prefetch_related('afield', 'afield__bmodel_field', 'afield__bmodel_field__cmodel_field')

Seond, вы должны использовать 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()
...