Issue
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': '[email protected]', '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)
Solution
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())
Answered By - Detlef
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.