I think the problem is username.data
should be form.username.data
but I don't know how to add form
in check_if_username_not_in_db.
I also want the functions to be outside RegistrationForm.
The error is located below. The error is triggered by the line
if form.validate_on_submit():
Traceback (most recent call last):
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\sqlalchemy\engine\base.py", line 1819, in _execute_context
self.dialect.do_execute(
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\sqlalchemy\engine\default.py", line 732, in do_execute
cursor.execute(statement, parameters)
sqlite3.InterfaceError: Error binding parameter 0 - probably unsupported type.
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\flask\app.py", line 2091, in __call__
return self.wsgi_app(environ, start_response)
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\flask\app.py", line 2076, in wsgi_app
response = self.handle_exception(e)
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\flask\app.py", line 2073, in wsgi_app
response = self.full_dispatch_request()
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\flask\app.py", line 1518, in full_dispatch_request
rv = self.handle_user_exception(e)
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\flask\app.py", line 1516, in full_dispatch_request
rv = self.dispatch_request()
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\flask\app.py", line 1502, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
File "C:\Users\user\OneDrive\Desktop\flaskcodeusethis\flaskblog2\app\auth\routes.py", line 152, in register
if form.validate_on_submit():
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\flask_wtf\form.py", line 86, in validate_on_submit
return self.is_submitted() and self.validate()
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\wtforms\form.py", line 318, in validate
return super(Form, self).validate(extra)
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\wtforms\form.py", line 150, in validate
if not field.validate(self, extra):
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\wtforms\fields\core.py", line 226, in validate
stop_validation = self._run_validation_chain(form, chain)
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\wtforms\fields\core.py", line 246, in _run_validation_chain
validator(form, self)
File "C:\Users\user\OneDrive\Desktop\flaskcodeusethis\flaskblog2\app\auth\functions.py", line 107, in check_if_username_not_in_db
if User.query.filter_by(username=username.data).first():
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\sqlalchemy\orm\query.py", line 2819, in first
return self.limit(1)._iter().first()
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\sqlalchemy\orm\query.py", line 2903, in _iter
result = self.session.execute(
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\sqlalchemy\orm\session.py", line 1712, in execute
result = conn._execute_20(statement, params or {}, execution_options)
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\sqlalchemy\engine\base.py", line 1631, in _execute_20
return meth(self, args_10style, kwargs_10style, execution_options)
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\sqlalchemy\sql\elements.py", line 332, in _execute_on_connection
return connection._execute_clauseelement(
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\sqlalchemy\engine\base.py", line 1498, in _execute_clauseelement
ret = self._execute_context(
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\sqlalchemy\engine\base.py", line 1862, in _execute_context
self._handle_dbapi_exception(
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\sqlalchemy\engine\base.py", line 2043, in _handle_dbapi_exception
util.raise_(
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\sqlalchemy\util\compat.py", line 208, in raise_
raise exception
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\sqlalchemy\engine\base.py", line 1819, in _execute_context
self.dialect.do_execute(
File "C:\Users\user\Anaconda3\envs\py\lib\site-packages\sqlalchemy\engine\default.py", line 732, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.InterfaceError: (sqlite3.InterfaceError) Error binding parameter 0 - probably unsupported type.
[SQL: SELECT user.id AS user_id, user.username AS user_username, user.hashed_password AS user_hashed_password, user.email AS user_email, user.registration_confirmation_email AS user_registration_confirmation_email, user.profile_pic_name AS user_profile_pic_name
FROM user
WHERE user.username = ?
LIMIT ? OFFSET ?]
[parameters: ({'username': 'arjipajgrpjg', 'email': 'fowomek545@fesgrid.com', 'password': 'arjipajgrpjg', 'confirm_password': 'arjipajgrpjg', 'csrf_token': 'IjdhMjA1OTU0ZWJiZGVlYmY5YzI5NDllNTlkOGY2ZWM2NmJhMzg5MmIi.ZRj5wg.8oHbeEs6RH2JNylJDMg7z9IhvpA'}, 1, 0)]
(Background on this error at: https://sqlalche.me/e/14/rvf5)
Here is the documentation on custom validators https://wtforms.readthedocs.io/en/2.3.x/validators/
Here is the code.
auth/functions.py
# custom validator
def check_if_username_not_in_db(username, self):
if the username is not in the db the code works,
if not it raises an ValidationError.
This runs in the RegistrationForm in username column
'''
if User.query.filter_by(username=username.data).first():
raise ValidationError('The username is already taken. Please select another username for registration.') # okay wording?
else:
flash('Success the username is not taken and you can successfully register.')
return None
auth/forms.py
class RegistrationForm(FlaskForm):
'''
This is in /register route.
The forms are username, email, password and confirm_password
'''
username = StringField('Username',validators=
[
DataRequired(message='Username is required'),
Length(min=2, max=25 , message='Must be between 2 and 25 characters'),
check_if_username_not_in_db
routes.py
@auth.route("/register", methods = \['POST', 'GET'\])
def register():
# if the user is logged in make so they can't go to the register page.
if current_user.is_authenticated:
return redirect(url_for(('auth.home')))
form = RegistrationForm()
# form.validate_on_submit(): are always the same line of render template to always allow a get request.
if form.validate_on_submit():
username_form = form.username.data
# more code ...
return render_template('register.html',title='register', form=form)
If you write your validator this way, note that the first argument is the form and the second is the input field.
The following code should fix your problem.
def check_if_username_not_in_db(form, field):
if User.query.filter_by(username=field.data).first():
raise ValidationError('The username is already taken.')
Here is the complete code of my stripped down example.
from flask import (
Flask,
render_template,
request
)
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import DataRequired, Length, ValidationError
app = Flask(__name__)
app.config.from_mapping(
SECRET_KEY='your secret here',
SQLALCHEMY_DATABASE_URI='sqlite:///users.db'
)
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String, unique=True)
def check_if_username_not_in_db(form, field):
if User.query.filter_by(username=field.data).first():
raise ValidationError('The username is already taken.')
class RegistrationForm(FlaskForm):
username = StringField('Username',
validators=[
DataRequired(),
Length(min=2, max=25),
check_if_username_not_in_db
]
)
with app.app_context():
db.drop_all()
db.create_all()
user = User(username='jrgop')
db.session.add(user)
db.session.commit()
@app.route('/register', methods=['GET', 'POST'])
def register():
form = RegistrationForm(request.form)
if form.validate_on_submit():
user = User()
form.populate_obj(user)
db.session.add(user)
db.session.commit()
return render_template('register.html', **locals())