Django 模板 - 如何在给定索引号(由迭代器生成)的情况下访问表单(上下文)中的表单

Django template - how to access form in forms (context) given an index number (generated by an iterator)

我有两种形式 - 源形式和结果形式。

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)生成一个容器,其中包含 source_form 和 result_form,如下所示。

template.html

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

背景:我有一个 javascript 队列,它一次取消隐藏一个 primary_container 进行处理;当用户处理队列中的下一个表单集时,我隐藏了 "just-processed" 容器并在后台填充它。目的是最小化表单填充时的等待时间。

如果我硬编码 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 %}

但是,在给定索引 i 的情况下,是否有更简单的方法在 forms 中获得正确的 form

Django 模板引擎设计 不允许您进行索引。

答案是使用 custom tag 来做索引(或者使用 Jinja 模板引擎,如果这是唯一需要解决的问题的话,这有点像大锤)。这是我之前写的,用于索引类似 dict 的实体。

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 %}