I have created a signup form using wtforms. I am using FormField in it so that I don't have to repeat some of the elements of the form again. But whenever I click on the Submit button it always give me false on validate_on_submit method invocation. Not getting why is this happening.
My form.py
is as follows:
class ProfileInfoForm(Form):
firstname = TextField('firstname', validators=
[validators.Required("Please enter First name.")])
lastname = TextField('lastname', validators=
[validators.Required("Please enter Last name.")])
email = EmailField('email', validators=
[validators.Required("Please enter your valid email.")])
gender = RadioField('gender', validators=
[validators.Required("Please select gender")],
choices=[('female', 'Female'), ('male', 'Male')])
dob = TextField('dob', validators=
[validators.Required("Please select date of birth.")])
languages = SelectMultipleField('languages', choices=[('', '')],
validators=
[validators.Required("Please select\
atleast one \
language.")])
class RegistrationForm(Form):
profilefield = FormField(ProfileInfoForm)
password = PasswordField('password',
validators=
[validators.Required("Please enter password."),
validators.Length(min=8),
validators.EqualTo('confirm_password',
message='Password and confirm\
password must match')])
confirm_password = PasswordField('confirm_password',
validators=
[validators.Required("Please enter\
confirm password.")])
tnc = BooleanField('tnc', validators=
[validators.Required("Please select Terms and \
Conditions")], default=False)
submit = SubmitField('Create My Account')
Signup
method is as follows:
@module.route('/signup', methods=['GET', 'POST'])
@handle_error
def signup():
if hasattr(g, 'user') and g.user:
# TODO: do some operations if needed else keep it blank
return redirect(url_for('index'))
else:
signup_form = RegistrationForm()
# Add choices for the user
signup_form.profilefield.languages.choices = getLanguages()
if signup_form.validate_on_submit():
firstname = signup_form.profilefield.firstname.data
lastname = signup_form.profilefield.lastname.data
email = signup_form.profilefield.email.data
password = signup_form.password.data
# confirm_password = signup_form.confirm_password.data
gender = signup_form.profilefield.gender.data
dob = signup_form.profilefield.dob.data
languages = signup_form.profilefield.languages.data
tnc = signup_form.tnc.data
payload = {'firstname': firstname, 'lastname': lastname,
'email': email, 'password': password, 'gender': gender,
'dob': dob, 'languages': languages,
'tnc': ('1' if tnc else '0')}
try:
buildApiUrl = BuildApiUrl()
response = requests.post(buildApiUrl.getUrl("user", "signup"),
data=payload)
if response.status_code == requests.codes.ok:
data = json.loads(response.text)
if 'status' in data and data['status'] != 200:
flash(data['message'], category="error")
else:
flash(data['message'] +
': Your account is created successfully! ' +
'Please login to your account!',
category="success")
return redirect(url_for('index'))
except requests.exceptions.RequestException:
flash('Internal Server side error occured', category="error")
return redirect(url_for('server_error', e='500'))
return render_template('public/index.html',
signup_form=signup_form, login_form=LoginForm())
HTML form is present on gist here
FYI: I am putting all the required fields with actual data needed. Still getting false when I call validate_on_submit(). What is wrong in my code?
EDIT: getLanguages is a method that retrieves languages from database and put in select list. This functionality is happening as expected and I can get list of languages.
Edit 2: Realize one thing here. This is happening due to FormField, since I tested by adding all the fields of ProfileInfoForm() into RegistrationForm() method, and everything worked just fine and I could signup. So some issue with the FormField or the way I am using it, but not sure where it is going wrong.
Found out that the problem is not with FormField but with my ProfileInfoForm(). It returns false always. Not yet got reason but I think I may have to write my own validation for that matter. Any thoughts?
Edit:
On dump I got following (used pprint here):
{'SECRET_KEY': '1e4c35233e50840483467e8d6cfe556c',
'_errors': None,
'_fields': {'csrf_token': <wtforms.ext.csrf.fields.CSRFTokenField object at 0x2207290>,
'dob': <wtforms.fields.simple.TextField object at 0x2207650>,
'email': <flask_wtf.html5.EmailField object at 0x22074d0>,
'firstname': <wtforms.fields.simple.TextField object at 0x2207350>,
'gender': <wtforms.fields.core.RadioField object at 0x2207590>,
'languages': <wtforms.fields.core.SelectMultipleField object at 0x2207710>,
'lastname': <wtforms.fields.simple.TextField object at 0x2207410>},
'_prefix': u'profilefield-',
'csrf_enabled': True,
'csrf_token': <wtforms.ext.csrf.fields.CSRFTokenField object at 0x2207290>,
'dob': <wtforms.fields.simple.TextField object at 0x2207650>,
'email': <flask_wtf.html5.EmailField object at 0x22074d0>,
'firstname': <wtforms.fields.simple.TextField object at 0x2207350>,
'gender': <wtforms.fields.core.RadioField object at 0x2207590>,
'languages': <wtforms.fields.core.SelectMultipleField object at 0x2207710>,
'lastname': <wtforms.fields.simple.TextField object at 0x2207410>}
Edit:
I dig little bit and found that the error is generated is due to csrf token missing. But I have included {{ signup_form.hidden_tag() }}
in my form template in html. and I can see hidden tag in html generated when I do inspect element and can see csrf_token field with hash value. So what is wrong in here?
I solved my problem with the following function:
I added this function in
ProfileInfoForm()
The issue was
FormField
includescsrf_token
field as well as Actual form, i.e.,RegistrationForm
was also including csrf_token, so there were twocsrf_token
which were to be verified and only one was getting rendered actually in form. So, I disabledcsrf_token
inProfileInfoForm
so when FormField rendered it, it hadcsrf_token = False
.And
RegistrationForm
does havecsrf_token
enabled still now so the form is still safe.My Guess is this does also required to be done in
FormField
as well.FYI: This solution might be wrong due to my interpretation of the FormField code. SO please correct me if I am wrong in above solution.
I had the same issue and I was able to fix it.
The problem was related to the fact that the LoginForm had the id and username with a validators while the html form was not requiring the information