6

I am building a very simple Sign Up form with flask and I wanted to customize the error message for DataRequired and Email validators, however it seems my custom messages are being ignored and the default messages are being printed. Below is my code snippet

forms.py

class SignUp(FlaskForm):
    username = StringField('Username', validators=[DataRequired(message='Must be filled'), length(min=4, max=10)])
    email = EmailField('Email', validators=[DataRequired(message='Email can\'t be blank'),
                                            Email(message='valid email address required')])
    password = PasswordField('Password', validators=[DataRequired()])
    confirm_password = PasswordField('Confirm Password',
                                     validators=[DataRequired(), EqualTo('password', 'Passwords must match')])
    submit = SubmitField('Register')

signup.html

{% extends "base.html" %}
{% from "jinja_helpers.html" import render_field %}
{% from "jinja_helpers.html" import render_button %}
{% block body %}
    <div class="container mt-4">
        <form action="" method="POST">
            {{ form.hidden_tag() }}
            {{ render_field(form.username) }}
            {{ render_field(form.email) }}
            {{ render_field(form.password) }}
            {{ render_field(form.confirm_password) }}
            {{ render_button(form.submit) }}
        </form>
        <div class="form-row mt-3">
            <small class="text-muted">Already have an account ? <a href="{{ url_for('login') }}">Log In</a></small>
        </div>
    </div>

{% endblock %}

jinja_helpers.html

{% macro render_field(field) %}
    <div class="form-group">
        {{ field.label(class="form-control-label font-weight-bold text-muted") }}
        {% if field.errors %}
            {{ field(class="form-control is-invalid") }}
            <div class="invalid-feedback">
                {% for error in field.errors %}
                    <span>{{ error }}</span>
                {% endfor %}
            </div>
        {% else %}
            {{ field(class="form-control") }}
        {% endif %}


    </div>
{% endmacro %}


{%  macro render_button(button) %}
    {{ button(class="btn btn-dark") }}
{%  endmacro %}

On the form when I leave the username or email fields blank, the validation pop up message I get is "Please fill out this field" which is default I guess. I also tried to print form.errors when I leave this fields blank and strangely the errors dictionary is empty.

views.py

@app.route('/signup', methods=['GET', 'POST'])
def signup():
    form = SignUp()
    print(f'------{form.errors}')
    if form.validate_on_submit():
        username = form.username.data
        password = form.password.data
        user = User(username, password)
        db.session.add(user)
        db.session.commit()
        flash('Account created successfully !', 'success')
        return redirect(url_for("login"))
    return render_template("signup.html", form=form, title='App-Sign Up')

And this is what I get

------{}
127.0.0.1 - - [25/Jan/2019 19:08:34] "GET /signup HTTP/1.1" 200 -
127.0.0.1 - - [25/Jan/2019 19:08:34] "GET /static/css/main.css HTTP/1.1" 404 -

So why these errors are not being added the errors and why the custom messages are not taking effect.Are these related some how ?

Rohit
  • 3,659
  • 3
  • 35
  • 57
  • Can you update your `signup.html`? – Chien Nguyen Jan 28 '19 at 07:31
  • update `signup.html` to what change ? You mean i should post `signup.html`, ok will do. – Rohit Jan 28 '19 at 07:33
  • Oh sorry, can you add the content of signup.html to your post – Chien Nguyen Jan 28 '19 at 07:35
  • Strange, I tried your code and it still works fine. – Chien Nguyen Jan 28 '19 at 08:19
  • What do you mean it works fine, try putting a custom message for `DataRequired` and `Email` validators and then try to either leave the fields blank and for email try putting some wrong value and see what validation message you get. – Rohit Jan 28 '19 at 08:21
  • yeah, your custom messages work fine. – Chien Nguyen Jan 28 '19 at 08:22
  • `form.errors` is blank. But the `render_field` still works – Chien Nguyen Jan 28 '19 at 08:24
  • what error message you get for `DataRequired` and `Email` validators. On which browser you tried? I tested this on both `chrome` and `firefox` and I could no get it work. – Rohit Jan 28 '19 at 08:25
  • Here is what I got https://imgur.com/a/MoKAznz – Chien Nguyen Jan 28 '19 at 08:30
  • I'm using python 3.7, flask 1.0.2, flask_wtf 0.14.2, wtforms 2.2.1. And I tested my app in Chrome – Chien Nguyen Jan 28 '19 at 08:32
  • I am use exactly similar setup and it simply does not work for me. Not sure what is wrong here..I guess bootstrap may be causing this issue. – Rohit Jan 28 '19 at 09:23
  • 1
    Ok. I got it, the message you seen is default of HTML5. Refer here: https://www.w3schools.com/tags/tryit.asp?filename=tryhtml5_input_required You can read here to disable it: https://stackoverflow.com/questions/50787904/how-to-override-the-html-default-please-fill-out-this-field-when-validation-fa?noredirect=1&lq=1 – Chien Nguyen Jan 28 '19 at 09:26

1 Answers1

6

The reason custom validation message for DataRequired and Email validator was because of the application client which is browser is using the defualt message for these validators. The way to override that default is by appending the novalidate message to the html form.

This tells the browser to stop doing the form validations by itself, so that it can be handled by the backend which in this case is flask.

This was the only change I had to make to my signup.html and it worked just fine.

Rohit
  • 3,659
  • 3
  • 35
  • 57