Issue
so after a user complained an error message, I discovered that my bank account field was not validating a length validator (WTForm). I disabled the length validator and implemented it myself. The error I therefore received was AttributeError: 'NoneType' object has no attribute 'length'
and if I tried, AttributeError: 'NoneType' object has no attribute 'isdigit'
. Clearly something was wrong. I have countless other forms all that behave perfectly, except this one. I cannot FOR THE LIFE of me, understand why this is. Everything seems to be setup properly. Here is my code:
Form
class onboard_form(FlaskForm):
full_name = StringField('Full Name (as it appears on your bank account)', validators=[
InputRequired(message='Please enter a valid name.')])
sort_codeone = StringField('Sort Code', validators=[(InputRequired(
message='Please enter a valid sort code.'))])
sort_codetwo = StringField('...', validators=[
InputRequired(message="Please enter a valid sort code.")])
sort_codethree = StringField('...', validators=[
InputRequired(message='Please enter a valid sort code.')])
account_number = StringField('Account Number', validators=[
InputRequired(message='Please enter a valid account number.')])
comfirm_account_number = StringField('Confirm Account Number', validators=[
InputRequired(message='Please enter a valid account number.')])
terms = BooleanField("I understand that I am responsible for providing a valid bank account.", validators=[
InputRequired(message='Please accept the terms and conditions.')])
def validate(self, extra_validators=None):
if super().validate(extra_validators):
# Check is sort code is valid
if not ((self.sort_codeone.data).isdigit() and (self.sort_codetwo.data).isdigit() and (self.sort_codethree.data).isdigit()):
self.sort_codeone.errors.append(
'Please enter a valid sort code.')
return False
if (((self.sort_codeone.data).length() != 2) or ((self.sort_codetwo.data).length() != 2) or ((self.sort_codethree.data).length() != 2)):
self.sort_codeone.errors.append(
'Please enter a valid sort code.')
return False
# Check account number is valid
if ((self.account_number.data).length != 8):
self.account_number.errors.append(
'Please enter a valid account number.')
return False
if ((self.account_number.data) != (self.comfirm_account_number).data):
self.comfirm_account_number.errors.append(
"Please enter the same value as above.")
else:
return True
Page that calls it
@app.route('/onboard', methods=["GET", "POST"])
@login_required
def onboard():
name = Users.get_by_id(session["user_id"]).first_name + " " + Users.get_by_id(session["user_id"]).last_name
form = onboard_form()
form.full_name.default = name
form.process()
if request.method == "POST":
print(form.sort_codeone)
if form.validate_on_submit():
sort_code = form.sort_code_1.data + "-" + \
form.sort_code_2.data + "-" + form.sort_code_3.data
Users.update(bank_full_name=form.full_name.data, bank_sort_code=sort_code,
bank_account_number=form.account_number.data).where(Users.id == session["user_id"]).execute()
return redirect('/newevent')
else:
print(form.errors)
return render_template('bank-details.html', form=form)
else:
return render_template('bank-details.html', form=form)
Html Template
{% extends "layout.html" %}
{% block title %}
Enter Bank Details
{% endblock %}
{% block main %}
<h3 class="py-5 text-4xl text-center">Onboard</h3>
<p class="text-center">To start adding events, please enter your bank details so that people can buy tickets from you!
</p>
<form id="form" action="/onboard" method="post" class="px-8 pt-6 pb-8 mb-4 rounded">
{{ form.csrf_token }}
<div class="text-center mb-4">
{{ form.full_name.label(class="block mb-2 text-sm font-medium text-gray-900") }}
{{ form.full_name(class_="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5", placeholder="John Smith") }}
<p class="mt-2 text-sm text-red-600 dark:text-red-500">{{ form.full_name.errors[0] }}</p>
</div>
<div class="flex justify-center">
<div class="mb-4 px-2">
{{ form.sort_codeone.label(class_="block mb-2 text-sm font-medium text-gray-900") }}
{{ form.sort_codeone(class_="w-full bg-gray-50 border border-gray-300 text-sm leading-tight text-gray-700 border rounded appearance-none focus:ring-blue-500 focus:border-blue-500 block p-2.5", placeholder="67") }}
</div>
<div class="mb-4 px-2">
<p class="text-xl pt-8">-</p>
</div>
<div class="mb-4 px-2">
{{ form.sort_codetwo.label(class_="block mb-2 text-sm font-medium text-gray-900") }}
{{ form.sort_codetwo(class_="w-full bg-gray-50 border border-gray-300 text-sm leading-tight text-gray-700 border rounded appearance-none focus:ring-blue-500 focus:border-blue-500 block p-2.5", placeholder="34") }}
</div>
<div class="mb-4 px-2">
<p class="text-xl pt-8">-</p>
</div>
<div class="mb-4 px-2">
{{ form.sort_codethree.label(class_="block mb-2 text-sm font-medium text-gray-900") }}
{{ form.sort_codethree(class_="w-full bg-gray-50 border border-gray-300 text-sm leading-tight text-gray-700 border rounded appearance-none focus:ring-blue-500 focus:border-blue-500 block p-2.5", placeholder="75") }}
</div>
</div>
<p class="text-center mb-4 text-sm text-red-600 dark:text-red-500">{{ form.sort_codeone.errors[0] }}</p>
<div class="text-center mb-4 px-2">
{{ form.account_number.label(class_="block mb-2 text-sm font-medium text-gray-900") }}
{{ form.account_number(class_="w-full bg-gray-50 border border-gray-300 text-sm leading-tight text-gray-700 border rounded appearance-none focus:ring-blue-500 focus:border-blue-500 block p-2.5", placeholder="12345678") }}
<p class="mt-2 text-sm text-red-600 dark:text-red-500">{{ form.account_number.errors[0] }}</p>
</div>
<div class="text-center mb-4 px-2">
{{ form.comfirm_account_number.label(class_="block mb-2 text-sm font-medium text-gray-900") }}
{{ form.comfirm_account_number(class_="w-full bg-gray-50 border border-gray-300 text-sm leading-tight text-gray-700 border rounded appearance-none focus:ring-blue-500 focus:border-blue-500 block p-2.5", placeholder="12345678") }}
<p class="mt-2 text-sm text-red-600 dark:text-red-500">{{ form.comfirm_account_number.errors[0] }}</p>
</div>
<div class="py-3 flex items-center mb-4">
{{ form.terms(class_="w-4 h-4 text-blue-600 bg-gray-100 rounded border-gray-300 focus:ring-sky-500") }}
{{ form.terms.label(class="ml-3 text-sm font-medium text-gray-900") }}
<p class="mt-2 text-sm text-red-600 dark:text-red-500">{{ form.terms.errors[0] }}</p>
</div>
<br>
<div class="mb-6 text-center">
<button
class="text-white bg-sky-700 hover:bg-sky-800 focus:ring-4 focus:ring-sky-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center"
type="submit">
Confirm
</button>
</div>
</form>
{% endblock %}
Again, I have countless other forms and I don’t understand what’s wrong here!
Solution
I figured it out, I had an extra line:
form.process()
Why I honestly don’t know how it got there but it wiped the form. Very strange
Answered By – Matthieu B
This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0