Using Flask + Flask-Classy + WTForms, I am trying to implement a route, such that, when user having error in their input form, application will presented again that form to the user, complete with what user already filled. This way, user didn't have to worried of typing again all the form input : (s)he can correct the errors.
These are code from my class UserView(FlaskView) which is a flask-classy class :
def post(self):
form = forms.UserForm(request.form)
if form.validate():
if form.id.data=='':
user = models.Users()
form.populate_obj(user)
user.id = None
db.session.add(user)
else:
user = models.Users.query.get(form.id.data)
form.populate_obj(user)
db.session.commit()
return redirect(url_for('UserView:index'))
else:
return redirect(url_for('UserView:validation_error', error_form=form))
def validation_error(self, error_form):
return render_template('users/form.html', form=error_form)
You can see that in this attempt, I try to create another method : validation_error, with argument --that in my expectation-- should contain all the form data. But, turns out I got Jinja2 exception, UndefinedError: 'unicode object' has no attribute 'hidden_tag'. As I inspect it, after having been in validation_error, that form object is somewhat changed from UserForm into somekind of unicode object.
Any suggestion? Or, is it that I try to solve this problem in a wrong direction?
EDIT 1 : Elaborate more on how to display the error
As @Rawrgulmuffins added an answer on how to display the error inline (which I think is the best way, as the page will not get jumpy), here I pasted the code in my layout.html that list all the errors. It may not as good as an inline error display, but I think it's the easiest way there is. First I do an if for the form object, as this code is also exist for all page (I maybe refactored it even more)
{% if form %}
{% for error in form.errors %}
<div class="alert alert-error">
<a class="close" data-dismiss="alert">×</a>
<strong>{{ form[error].label }} {{form.errors[error][0] }}</strong>
</div>
{% endfor %}
{% endif %}
Screenshot given :

I'm adding my answer to expand swdev's answer for anyone that doesn't understand why he can just render the template and show the errors.
Each field in a form contains a errors attribute that will be populated after validation (after form.validate()). These errors will be contained in the form object. So you can say something like,
{% if field.errors %}
<span class="error help-inline">{{ field.errors|join(', ') }}</span>
{% endif %}
example source file. This is very nifty because you can just say
return render_template('users/form.html', form=form)
and if it's the first render get a error free form and display errors only on the second rendering of the form.
I'm not sure why Swdev attempt to redirect the form caused it to be manipulated right now. I'm looking through the Werkzeug code right now to see if I can find an answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With