2

I'm using Flask to create a web app. I'm trying to create a form using Flask-WTForms by iterating through a list passed in the render_template() method. However, I can't reference the variable in the for-loop inside the template.

View

class FormExample(Form):
    category1 = StringField("Category 1")
    category2 = StringField("Category 2")

categories = ['category1', 'category2']
def form():
    form = FormExample(request.form)
    return_template("form.html", categories=categories, form=form)

_formhelpers.html (suggested to use under the docs)

{% macro render_field(field) %}
  <dt>{{ field.label }}
  <dd>{{ field(**kwargs)|safe }}
  {% if field.errors %}
    {% for error in field.errors %}
      {{ error }}
    {% endfor %}
  {% endif %}
  </dd>
{% endmacro %}

Template (form.html)

<form method="POST">
  {% for category in categories %}
    {{render_field(form.category)}}
  {% endfor %}
</form>

When trying to reference form.category in form.html I'm given the following error through the Flask debugger:

jinja2.exceptions.UndefinedError: '__main__.EvaluateCaseForm object' has no attribute 'category'

I've already looked at the official documentation here and couldn't find the answer. I've also tried referencing {{render_field({{ form.category }})}}, {{render_field(form.{{category}})}}, and {{render_field({% form.category %})}}

Is there a way to reference the for-loop variable category inside the render_field() method?

2
  • Why not {% for field in form %}{{ render_field(field) }}{% endfor %}? Are you trying to handle categories not matching the fields in your form? Commented Aug 4, 2018 at 5:01
  • @snakecharmerb the issue I'm having is that form.category is being read as though the variable form has an attribute called category. However, I want the value for category to be the value based on the for-loop. Does that make sense? Commented Aug 6, 2018 at 20:47

2 Answers 2

1

WTForms uses the __getitem__ protocol to allow fields can be accessed like dictionary values, for example form[fieldname].

So in your code, replace form.category with form[category]:

<form method="POST">
  {% for category in categories %}
    {{ render_field(form[category]) }}
  {% endfor %}
</form>
Sign up to request clarification or add additional context in comments.

Comments

0

Is there a way to reference the for-loop variable category inside the render_field() method?

Yup:

   {% for category in categories %}
     {{render_field(category)}}
   {% endfor %}

1 Comment

I apologize I don't think I made myself clear. I need to access the form attributes form.category1 and form.category2. I just updated the question with a bit more information to hopefully make it more clear. Trying to pass in (category) just passes in a string and not a form attribute.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.