I am creating a form for the user to enter a valid UK postcode. I currently have the following code for the form:
class RegisterForm(Form): first_name = StringField('First Name', validators=[DataRequired(), validators.Length(min=1, max=50)]) last_name = StringField('Last Name', validators=[DataRequired(), validators.Length(min=1, max=50)]) centre_id = StringField('Centre ID', validators=[DataRequired(), validators.Length(min=1, max=11)]) doctor_id = StringField('Doctor ID', validators=[DataRequired(), validators.Length(min=1, max=11)]) address = StringField('Address Line 1', validators=[DataRequired(), validators.Length(min=1, max=100)]) town_name = StringField('Town Name', validators=[DataRequired(), validators.Length(min=1, max=50)]) county_name = SelectField('County Name', choices=[('antrim', 'Antrim'), ('armagh', 'Armagh'), ('down', 'Down'), ('derry/londonderry', 'Derry/Londonderry'), ('fermanagh', 'Fermanagh'), ('tyrone', 'Tyrone')], validators=[DataRequired()]) postcode = StringField('Postcode', validators=[DataRequired(), validation.is_valid_postcode]) telephone_number = TelField('Telephone Number', validators=[DataRequired(), validators.Length(min=11, max=11)]) email_address = EmailField('Email Address', validators=[DataRequired()]) patient_username = StringField('Username', {validators.DataRequired(), validators.EqualTo('confirm_patient_username', message='Usernames do not match')}) confirm_patient_username = StringField('Confirm Username') patient_password = PasswordField('Password', {validators.DataRequired(),validators.EqualTo('confirm_patient_password', message='Passwords do not match')}) confirm_patient_password = PasswordField('Confirm Password')
and the template is:
{% extends 'patient/patient_login_layout.html' %} {% block body %} <h1>Patient Register</h1> {% from 'includes/_formhelpers.html' import render_field %} <form method="POST" action=""> <div class="form-group"> {{render_field(form.first_name, class="form-control")}} </div> <div class="form-group"> {{render_field(form.last_name, class="form-control")}} </div> <div class="form-group"> {{render_field(form.centre_id, class="form-control")}} </div> <div class="form-group"> {{render_field(form.doctor_id, class="form-control")}} </div> <div class="form-group"> {{render_field(form.address, class="form-control")}} </div> <div class="form-group"> {{render_field(form.town_name, class="form-control")}} </div> <div class="form-group"> {{render_field(form.county_name, class="form-control")}} </div> <div class="form-group"> {{render_field(form.postcode, class="form-control")}} </div> <div class="form-group"> {{render_field(form.telephone_number, class="form-control")}} </div> <div class="form-group"> {{render_field(form.email_address, class="form-control")}} </div> <div class="form-group"> {{render_field(form.patient_username, class="form-control")}} </div> <div class="form-group"> {{render_field(form.confirm_patient_username, class="form-control")}} </div> <div class="form-group"> {{render_field(form.patient_password, class="form-control")}} </div> <div class="form-group"> {{render_field(form.confirm_patient_password, class="form-control")}} </div> <p><input type="submit" class="btn btn-primary" value="Submit"></p> </form> {% endblock %}
but getting the error: TypeError: argument of type ‘StringField’ is not iterable.
What can I do to fix this?
Edit: Here are the complete form entry and the template for the webpage. Thanks a lot.
Advertisement
Answer
You are not using the WTForms validators correctly in your postcode
StringField
.
Declare a function that takes form and field parameters and raise an error if the post code is invalid, in this function you make use of the uk-postcode-utils is_valid_postcode
function, i.e.:
class RegisterForm(Form): # ... postcode = StringField('Postcode', validators=[DataRequired(), post_code_validator]) from wtforms.validators import ValidationError from ukpostcodeutils import validation def post_code_validator(form, field): # raise a validation error IF the post code doesn't validate if not validation.is_valid_postcode(field.data): raise ValidationError('Invalid UK Post Code')
Register the validator on the StringField:
class RegisterForm(Form): # ... postcode = StringField('Postcode', validators=[DataRequired(), post_code_validator]) # ...
If a post code field is being used in several forms you’re better off writing a class validator as outlined in the WTForms documentation.
Something like (untested):
from wtforms.validators import ValidationError from ukpostcodeutils import validation class PostCodeValidator(object): def __init__(self, message=None): if not message: message = u'Must be a valid UK Post Code' self.message = message def __call__(self, form, field): # raise a validation error IF the post code doesn't validate if not validation.is_valid_postcode(field.data): raise ValidationError('Invalid UK Post Code') post_code_validator = PostCodeValidator