Использование переменных в качестве полей формы в шаблоне формы Django

<here all loading of static , template_filters, crispy_forms >

<form>
{% for i in artifact_length %}
   {% with artifact_name="artifact"|artifact_name:forloop.counter0 %}
        {{form.artifact_name|as_crispy_field}}
   {% endwith %}
{%endfor%}
</form>

Это связанный код шаблона. Здесь я хочу вывести поля формы с именами artifact_0, artifact_1 как исходящие из формы. Переменная artifact_name внутри with работает нормально и возвращает ожидаемые идентификаторы artifact_0 , artifact_1, но я хочу использовать эти переменные как поля формы для отображения в виде as_crispy_field. Код {{form.artifact_name|as_crispy_field}} ничего не выводит, потому что он принимает форму за поле с именем artifact_name, а это не так. Вместо этого я хочу использовать значение переменной здесь.

forms.py

  class Someform(forms.form):
    def __init__(self, artifact_obj):
        super().__init__()
        count = 0
        for artifact in artifact_obj:
            self.fields[f'artifact_{count}'] = forms.CharField(widget=forms.NumberInput())
                count += 1
tags.py

@register.filter('artifact_name')
def get_artifact_name(artifact_prefix: str, counter: int):
    print('method', 'prefix', artifact_prefix, 'counter', counter)
    return f'{artifact_prefix}_{counter}'

Создается форма переменной длины. Как вforms.py создаются поля формы с artifact_count, где count может варьироваться от 0 до len объекта.

Для этого не нужно использовать фильтры / теги шаблонов и т.д. Простейшим решением будет перебор полей формы для их отображения:

<form>
{% for field in form %}
    {{ field|as_crispy_field }}
{%endfor%}
</form>

Это позволит перебрать все поля вашей формы.

Если вам особенно важен порядок этих полей, вы можете вызвать метод форм order_fields:

class Someform(forms.form):
    def __init__(self, artifact_obj, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for count, artifact in enumerate(artifact_obj):
            self.fields[f'artifact_{count}'] = forms.CharField(widget=forms.NumberInput())
        self.order_fields(["field_1", "field_2", ...] + [f"artifact_{i}" for i, _ in enumerate(artifact_obj)] + [..., "field_n"])

Если вы хотите отображать другие поля отдельно, вы можете добавить метод к вашей форме, который позволит вам перебирать эти поля в цикле:

class Someform(forms.form):
    def __init__(self, artifact_obj, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for count, artifact in enumerate(artifact_obj):
            self.fields[f'artifact_{count}'] = forms.CharField(widget=forms.NumberInput())
        self.artifact_length = len(artifact_obj)
    
    def artifact_fields(self):
        return [self[f'artifact_{i}'] for i in range(self.artifact_length)]

А затем перейдите по ним в шаблоне:

<form>
{% for field in form.artifact_fields %}
    {{ field|as_crispy_field }}
{%endfor%}
</form>
Вернуться на верх