Какова лучшая практика для передачи переменных в шаблоны? - PullRequest
0 голосов
/ 09 мая 2018

Я пишу веб-приложение, и мне было интересно, как лучше всего использовать переменные в шаблонах. Сейчас я запрашиваю модели в своих представлениях, а затем отправляю эти объекты в шаблоны.

Пример:

У меня есть структура и элементы управления, прикрепленные к этим структурам. Если я хочу отобразить все элементы управления для конкретных структур, я бы сделал это.

Модель:

# models.py
class Framework(models.Model):
    name = models.CharField(max_length=100)
    description = models.TextField(null=True)


class Control(models.Model):
    title = models.CharField(max_length=250)
    description = models.TextField()
    framework = models.ForeignKey(Framework,
                                on_delete=models.CASCADE,
                                verbose_name="related framework")
    category = models.ForeignKey(FrameworkCat,
                             on_delete=models.CASCADE,
                             verbose_name="related category",
                             null=True)

В просмотрах:

# views.py
def show_frameworks(request):
    frameworks = Framework.objects.all()
    controls = Control.objects.all()

    data['frameworks'] = frameworks
    data['controls'] = controls

   return render(request, 'show_frameworks.html', data)

А потом в шаблонах:

# templates/show_frameworks.html
<div>
{% for framework in frameworks %}
    <p>{{framework.name}}</p>
    {% for control in controls %}
        {% if control.framework == framework %}
            <p>{{control.title}}</p>
        {% endif %}
    {% endfor %}
{% endfor %}
</div>

Было бы это эффективно сделать или было бы быстрее / эффективнее сделать что-то вроде этого:

# views.py
def show_frameworks(request):
    controls = Control.objects.all().order_by('framework')

    data['controls'] = controls

   return render(request, 'show_frameworks.html', data)

А потом в шаблонах:

# templates/show_frameworks.html
<div>
{% for control in controls %}
    {% if forloop.first %}
        <p>{{control.framework.name}}</p>
        <p>{{control.title}}</p>
        {% with prevframework = control.framework %}
    {% else %}
        {% with curframework = control.framework %}
        {% if curframework != prevframework %}
            <p>{{control.framework.name}}</p>
            <p>{{control.title}}</p>
       {% else %}
            <p>{{control.title}}</p>
       {% endif %}
    {% with prevframework = control.framework %}
    {% endif %}
{% endfor %}
</div>

Это выглядит немного сложнее, но это означает, что мне придется отправлять меньше запросов в базу данных и отправлять данные в шаблон. Это простой пример, но в моем веб-приложении у меня есть довольно большая база данных на медленном хостинге, поэтому любая оптимизация приветствуется. Мой вопрос в основном здесь: будет ли последний более эффективным, потому что используется только один цикл for и только один запрос отправляется в базу данных? Или первый еще более эффективен, несмотря на использование двух циклов for, многократно повторяющихся над каждым элементом управления и отправляющих два запроса в базу данных?

Спасибо!

1 Ответ

0 голосов
/ 09 мая 2018

Переместите как можно больше логики в DB / обычный Python.

Вы можете использовать prefetch_related, который выбирает связанный controls для каждого framework и выполняет соединение в обычном Python. Не помещайте слишком много в шаблон, так как механизм шаблонов работает относительно медленнее, чем обычный Python, и ваш код менее удобен в обслуживании, если у вас слишком много:

def show_frameworks(request):
    frameworks = Framework.objects.prefetch_related('control_set').all()
    data['frameworks'] = frameworks
    return render(request, 'show_frameworks.html', data)

А потом:

<div>
{% for framework in frameworks %}
    <p>{{framework.name}}</p>
    {% for control in framework.control_set %}
         <p>{{control.title}}</p>
    {% endfor %}
{% endfor %}
</div>
...