Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the technique of presenting again form which contains error?

Tags:

python

flask

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 :

Validation error display

like image 550
swdev Avatar asked Dec 04 '25 05:12

swdev


1 Answers

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.

like image 66
AlexLordThorsen Avatar answered Dec 06 '25 22:12

AlexLordThorsen