25

I'm following a Flask tutorial from http://code.tutsplus.com/tutorials/intro-to-flask-adding-a-contact-page--net-28982 and am currently stuck on the validation step:

The old version had the following:

from flask.ext.wtf import Form, TextField, TextAreaField, SubmitField, validators, ValidationError

class ContactForm(Form):
name = TextField("Name",  [validators.Required("Please enter your name.")])
email = TextField("Email",  [validators.Required("Please enter your email address."), validators.Email("Please enter your email address.")])
submit = SubmitField("Send")

Reading the comments I updated it to this: (replaced validators.Required with InputRequired)

(same fields)  

class ContactForm(Form):  
name = TextField("Name", validators=[InputRequired('Please enter your name.')])
email = EmailField("Email",  validators=[InputRequired("Please enter your email address.")]), validators.Email("Please enter your email address.")])
submit = SubmitField("Send")

My only issue is I don't know what to do with the validators.Email. The error message I get is:

NameError: name 'validators' is not defined

I've looked over the documentation, perhaps I didn't delve deep enough but I can't seem to find an example for email validation.

lost9123193
  • 10,460
  • 26
  • 73
  • 113

6 Answers6

40

Try this:

from flask.ext.wtf import Form
from wtforms import validators
from wtforms.fields.html5 import EmailField

class ContactForm(Form):
    email = EmailField('Email address', [validators.DataRequired(), validators.Email()])
mehdix
  • 4,984
  • 1
  • 28
  • 36
  • 4
    "Note that this uses a very primitive regular expression and should only be used in instances where you later verify by other means, such as email activation or lookups." - [WTForms Validators documentation](http://wtforms.readthedocs.io/en/latest/validators.html) – Philippe Hebert May 13 '16 at 19:24
8

I worked through the same tutorial as a refresher (I hadn't looked at flask for a couple years).

The problem is due yo a change in Flask-WTF at version 0.9. Here, they say:

Note: From version 0.9.0, Flask-WTF will not import anything from wtforms, you need to import fields from wtforms.

To import directly, forms.py should read:

from flask.ext.wtf import Form
from wtforms import StringField, TextAreaField, SubmitField
from wtforms.validators import InputRequired, Email

class ContactForm(Form):
  name = StringField("Name",  [InputRequired("Please enter your name.")])
  email = StringField("Email",  [InputRequired("Please enter your email address."), Email("This field requires a valid email address")])
  subject = StringField("Subject",  [InputRequired("Please enter a subject.")])
  message = TextAreaField("Message",  [InputRequired("Not including a message would be stupid")])
  submit = SubmitField("Send")

Note that StringField replaces TextField and that InputRequired is preferred over DataRequired. It was personal preference to import the validators directly over importing the entire namespace. This also works: from wtforms import * and in the form class: name = StringField("Name", [validators.InputRequired("message")

While your updating to the latest version of Flask-WTF you might as well use validate_on_submit() in your view as well (as recommended here).

And the convenience validate_on_submit will check if it is a POST request and if it is valid.

cstrutton
  • 5,667
  • 3
  • 25
  • 32
4
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired, Email

class ContactForm(FlaskForm):  
    name = StringField("Name", validators=[DataRequired()])
    email = StringField("Email",  validators=[DataRequired(), Email()])
    submit = SubmitField("Send")
3
  from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, BooleanField, SubmitField 
  from wtforms.fields.html5 import EmailField 
  from wtforms.validators import DataRequired, Email

  class LoginForm(FlaskForm):
      username = StringField('Username', validators=[DataRequired()])
      email = EmailField('Email Address', validators=[DataRequired(), Email()])
      password = PasswordField('Password', validators=[DataRequired()])
      remember_me = BooleanField('Remember me')
      submit = SubmitField('Sign In')
J11
  • 455
  • 4
  • 8
2

The reason for this error is that you most likely imported the validators without namespace, using from foo import bar import statements.

To make it a bit more readable and to fix the syntax errors in your example code:

from flask.ext.wtf import Form
from wtforms import TextField, SubmitField
from wtforms.validators import InputRequired, Email
from wtforms.fields.html5 import EmailField  

class ContactForm(Form):  
    name = TextField("Name", validators=[InputRequired('Please enter your name.')])
    email = EmailField("Email",  validators=[InputRequired("Please enter your email address."), Email("Please enter your email address.")])
    submit = SubmitField("Send")

This only loads in the fields TextField, SubmitField and Email as well as only the InputRequired and Email validators. Then simply chain the validators in your validators keyword argument and you are good to go. Or, as @Mehdi Sadeghi pointed out in the code, directly supply a list of validators as the second argument to the field, in which case your email field would look like this:

email = EmailField("Email", [InputRequired("Please enter your email address."), Email("Please enter your email address.")])

Note that by importing only what you need using the syntax from foo import bar you are throwing away the modules namespace, as you also have noticed when you dropped the validators. prefix. Some find it better to leave this namespace, and thus use the dot notation, simply to prevent possible name clashes and to see right away to which module an object belongs (without needing to look back at the import statements).

The choice, as always, is yours!

Timusan
  • 3,255
  • 1
  • 22
  • 27
2

Just use pip to install email_validator e.g

pip install email_validator

Leo Awiti
  • 21
  • 3
  • Why do you have to use `email_validator`. You can perform without using it – PCM Jun 28 '21 at 09:58
  • 1
    For those getting "NameError: name 'validators' is not defined" one solution is to install an "email_validator" and keep their code as written while another solution is to recode. – Leo Awiti Jun 29 '21 at 12:58