1

I'm trying to make a uncertainty calculator, where I need a variable number of Fields (this is the final idea). However, while testing for number of 1 field of fields, I came across a issue. Instead of the fields being rendered in the page, there is only some random code in its place:

Result of the code below

I tried checking if the issue was related to them having the same name "values" or something, but it seems that is not the issue. I don't know what to try anymore.

forms.py

from flask.ext.wtf import Form
from wtforms import StringField, BooleanField, DecimalField
from wtforms.validators import DataRequired

class Receiver(Form):
    expression = StringField('expression', validators=[DataRequired()])
    # ve_list = [[StringField('expreson'), DecimalField('expression', places=10)], [StringField('expreson'), DecimalField('expression', places=10)]]
    # remember_me = BooleanField('remember_me', default=False)

    ve_list = [[DecimalField('value', validators=[DataRequired()]), DecimalField('value', validators=[DataRequired()])]]

The views.py:

from flask import render_template, flash, redirect
from app import app
from .forms import Receiver
@app.route('/login', methods=['GET', 'POST'])
def login():
    form = Receiver()
    return render_template('request.html', 
                           title='Calculate',
                           form=form)

request.html:

{% block content %}
  <h1>Error propagation calculator</h1>
  <form action="" method="post" name="login">
      {{ form.hidden_tag() }}
      <p>
          Please enter the expression:<br>
          {{ form.expression }}<br>
      </p>
          Enter the value and respective error:<br>
          {% for ve in form.ve_list %}
          {{ ve[0] }} +/- {{ ve[1] }}<br>
          {% endfor %} 
      <p><input type="submit" value="Calculate"></p>
  </form>
{% endblock %}
Kelthar
  • 124
  • 9
  • I think what you are looking for is this: http://stackoverflow.com/a/18267539/1051404 Also if you go on irc asking for help and are interacting with people don't just leave if you don't get an immediate answer. – castilho Feb 11 '16 at 19:31

2 Answers2

1

Fields are classes and need to be called in order to run their call method which will render the html to your page.

Example 1:

{{ form.expression() }}

Your field is rendering but it is best to call the field properly.

Edited:

Your list of fields is not going to work because you need to have an instantiated class attached to the form class attribute. When you load up the field like this it is an UnboundField.

unboundfield

I recommend adding fields dynamically in your view. You can see an answer to that problem here.

m1yag1
  • 819
  • 7
  • 11
  • Hmm, that makes sense, however form.expression was rendering even without the parentesis (with the I have the same result). And when I tried to add them so "ve" as you did, I get: "AttributeError: 'UnboundField' object has no attribute '__call__' " – Kelthar Feb 10 '16 at 21:52
  • @allg18, I'm assuming that is because my index is off. I see that the first field is a list inside of a list so it may need to be `ve[0][0]` or something like that. – m1yag1 Feb 10 '16 at 23:47
  • I think not, because "ve_list" is a list of lists, and I use "for ve in form.ve_list", so each ve is a list of DecimalFields, which is two elements long (and I call them with ve[0] and ve[1]) – Kelthar Feb 10 '16 at 23:50
  • Ok, sorry about that. The problem is when adding the list to the form you are getting an UnboundField. More than likely wt-forms needs to instantiate a field class and assign it to the attribute on the form class. What your doing is probably not going to work. See this answer: https://stackoverflow.com/questions/16406496/rendering-forms-with-flask-wtform – m1yag1 Feb 11 '16 at 00:08
  • @allg18, Could you mark this as answered b/c I believe I resolved your issue? – m1yag1 Feb 11 '16 at 01:59
1

The fields that are part of the form need to be class variables of the form class. If they are not, then WTForms is not going to find them, so they are never bound to the form.

If you want to add a list of fields, you can do so by setting the attributes on the Form class. Something like this:

class Receiver(Form):
    expression = StringField('expression', validators=[DataRequired()])

setattr(Receiver, 've_list0', DecimalField('value', validators=[DataRequired()]))
setattr(Receiver, 've_list1', DecimalField('value', validators=[DataRequired()]))

Then in the template, you can iterate on the form fields to render them, instead of rendering them one by one.

Miguel Grinberg
  • 65,299
  • 14
  • 133
  • 152