Django шаблон - как получить доступ к форме в формах (контексте) по заданному индексу (генерируется итератором) - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть две формы - исходная форма и форма результата.

Forms.py

class SourceForm(forms.Form):
    some_source_field = forms.forms.CharField(...)

class ResultForm(forms.Form):
    some_result_field = forms.forms.CharField(...)

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

Views.py

class MyView(Vew):

    def get(self, request):

        forms_to_render = 2

        SourceFormSet = formset_factory(SourceForm, extra=forms_to_render)
        ResultFormSet = formset_factory(ResultForm, extra=forms_to_render)

        context = {
            'source_forms': SourceFormSet,
            'result_forms': ResultFormSet,
            'init': range(0, forms_to_render),
        }

В моем шаблон, я хочу сгенерировать контейнер, для которого содержатся исходные и исходные формы для каждого из чисел в данном диапазоне (в данном случае 2), как показано ниже.

шаблон. html

{% for i in init %}
  <div class="container-fluid" id="primary_container_{{ i }}">
    {{ source_forms.i }}
    {{ result_forms.i }}
  </div>
{% endfor %}

Справочная информация: у меня есть очередь javascript, которая отображает одну primary_container за раз для обработки; Я скрываю «только что обработанный» контейнер и заполняю его в фоновом режиме, пока пользователь работает над следующим набором форм в очереди. Цель состоит в том, чтобы минимизировать время ожидания при заполнении формы.

Если я жестко закодирую значение индекса 0 или 1, форма будет отображаться.

{{ source_forms.0 }} <!-- works fine -->
{{ source_forms.1 }} <!-- works fine -->

Однако, это не работает

{% for i in init %}
  {{ source_forms.i }} <!-- doesn't render form -->
{% endfor %}

Я подумал, что, возможно, i больше не является правильным типом данных, поэтому я попробовал это, что также не работает

{% for i in init %}
  {% with forloop.counter0 as x %}
    {{ source_forms.x }} <!-- doesn't render form -->
  {% endwith %}
{% endfor %}

Я получил это работает следующим образом:

{% for i in init %}
  {% for form in source_forms %}
    {% if forloop.counter0 == i %}
      {{ form }} <!-- renders form -->
    {% endif %}
  {% endfor %}
{% endfor %}

Но есть ли более простой способ получить правильный form в forms с учетом индекса i?

1 Ответ

1 голос
/ 19 февраля 2020

Механизм шаблонов Django по дизайну не позволяет выполнять индексацию.

Ответ заключается в использовании пользовательского тега для индексации (или в использовании движка шаблонов Jinja, который является чем-то вроде кувалды, если это единственный орех, который можно взломать). Это тот, который я написал ранее, для индексации похожей на диктовку сущности.

from django import template
register = template.Library()

@register.filter
def lookup( d, key): 
    """ filter: d is dict-like. return d[key] with '' as default using get method """
    return d.get( key, '')

Использование: {{ dict_thing|lookup:key }}

В вашем случае я бы ожидал, что сработает следующее:

@register.filter
def index( lst, index): 
    return lst[index]

Использование: {{ source_forms|index:x }}

Примечание: в шаблоне | или : не допускается пробелов

Другой способ, который я использовал в прошлом, это передать функцию генератора (yield result) в контексте в шаблон, который затем можно перебрать в шаблоне, используя {% for x in generator %} Я думаю, Python zip может быть всем, что вам нужно здесь:

return render( ... context={
   'formpairs': zip( SourceFormSet, ResultFormSet), ...
})

и в шаблоне

{% for pair in formpairs %}
  <div class="container-fluid" id="primary_container_{{ forloop.counter }}">
  {{ pair.0 }}
  {{ pair.1 }}
  </div>
{% endfor %}
...