简体   繁体   中英

How can I render a FieldList of variable length in WTForms?

I'm trying to make a form to populate a calendar. The calendar can be five or seven days long, and I'd like to pass the number of days as an argument to the form. My form is defined like so:

class LoadForecastForm(Form):

    def __init__(self, n_days, *args, **kwargs):
        self.n_days = n_days
        super(LoadForecastForm, self).__init__(*args, **kwargs)
        self.day_values = FieldList(SelectField('Day Values', coerce=str, choices=[('low', 'Low'), ('medium', 'Medium'), ('high', 'High'), ('holiday', 'Holiday')]), min_entries=n_days, max_entries=n_days)
        self.send = SubmitField('Send Calendar')

It's rendered like so:

<form role="form" action="" method="POST">
{{ form.hidden_tag() }}
<div class="form-group row">
  {% for field in form.day_values %}
  <div class="col-sm-2">
    <div class="form-group{% if field.errors %} error {% endif %}">
      {% if label %}
        {{ field.label }}
      {% endif %}
      {{ field(**kwargs) }}
      {% for error in field.errors %}
        <span class="help-inline">[{{error}}]</span><br>
      {% endfor %}
    </div>
  </div>
  {% endfor %}
</div>
{{ form.send }}

The form page is failing to render; the traceback ends with:

File "project/populate_schedule.tpl.html", line 25, in block "page_content"
{% for field in day_values %}
TypeError: 'UnboundField' object is not iterable

n_days used to be hardcoded, and the fields were defined as class variables with no __init__() function, and there were no errors. How do I correctly define the field programmatically? I am using Python 2.7.

You need to leave the field definitions in the class body, otherwise they won't be picked up with the class is constructed. When the form instance is being initialised you can apply the max/min entries values to the fieldlist.

class F(Form):

    day_values = FieldList(SelectField('Day Values',
                           coerce=str,
                           choices=[('low', 'Low'), ('medium', 'Medium'),
                                    ('high', 'High'), ('holiday', 'Holiday')]))
    send = SubmitField('Send Calendar')

    def __init__(self, *args, **kwargs):
        ndays = kwargs.pop('n_days')
        super(F, self).__init__(*args, **kwargs)
        self.day_values.min_entries = n_days
        self.day_values.max_entries = n_days

Test:

n_days = 4
f = F(n_days=n_days)
for x in range(n_days):
    f.day_values.append_entry()
for field in f.day_values:
    print field()
    print

Output:

<select id="day_values-0" name="day_values-0"><option value="low">Low</option><option value="medium">Medium</option><option value="high">High</option><option value="holiday">Holiday</option></select>

<select id="day_values-1" name="day_values-1"><option value="low">Low</option><option value="medium">Medium</option><option value="high">High</option><option value="holiday">Holiday</option></select>

<select id="day_values-2" name="day_values-2"><option value="low">Low</option><option value="medium">Medium</option><option value="high">High</option><option value="holiday">Holiday</option></select>

<select id="day_values-3" name="day_values-3"><option value="low">Low</option><option value="medium">Medium</option><option value="high">High</option><option value="holiday">Holiday</option></select>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM