Search code examples
flaskflask-wtformsflask-login

How to fix TypeError: validate() got an unexpected keyword argument 'extra_validators'?


I've put together basic login/register forms in a flask app using WTForms. I included parts of code from two files that I thought might be relevant.

I am getting the error:

Traceback (most recent call last):
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask/app.py", line 2548, in __call__
return self.wsgi_app(environ, start_response)
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask/app.py", line 2528, in wsgi_app
response = self.handle_exception(e)
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask/app.py", line 2525, in wsgi_app
response = self.full_dispatch_request()
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask/app.py", line 1822, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask/app.py", line 1820, in full_dispatch_request
rv = self.dispatch_request()
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask/app.py", line 1796, in dispatch_request
return self.ensure_sync(self.view_functions\[rule.endpoint\])(\*\*view_args)
File "/home/neon/flask-app/src/accounts/views.py", line 18, in register
if form.validate_on_submit():
File "/home/neon/flask-app/venv/lib/python3.8/site-packages/flask_wtf/form.py", line 86, in validate_on_submit
return self.is_submitted() and self.validate(extra_validators=extra_validators)
TypeError: validate() got an unexpected keyword argument 'extra_validators'

This is my code:

src/accounts/forms.py

from flask_wtf import FlaskForm
from wtforms import EmailField, PasswordField
from wtforms.validators import DataRequired, Email, EqualTo, Length

from src.accounts.models import User


class RegisterForm(FlaskForm):
    email = EmailField(
        "Email", validators=[DataRequired(), Email(message=None), Length(min=6, max=40)]
    )
    password = PasswordField(
        "Password", validators=[DataRequired(), Length(min=6, max=25)]
    )
    confirm = PasswordField(
        "Repeat password",
        validators=[
            DataRequired(),
            EqualTo("password", message="Passwords must match."),
        ],
    )

    def validate(self):
        initial_validation = super(RegisterForm, self).validate()
        if not initial_validation:
            return False
        user = User.query.filter_by(email=self.email.data).first()
        if user:
            self.email.errors.append("Email already registered")
            return False
        if self.password.data != self.confirm.data:
            self.password.errors.append("Passwords must match")
            return False
        return True

src/accounts/views.py

from flask import Blueprint, flash, redirect, render_template, request, url_for
from flask_login import login_required, login_user, logout_user, current_user

from src import bcrypt, db
from src.accounts.models import User

from .forms import LoginForm, RegisterForm

accounts_bp = Blueprint("accounts", __name__)


@accounts_bp.route("/register", methods=["GET", "POST"])
def register():
    if current_user.is_authenticated:
        flash("You are already registered.", "info")
        return redirect(url_for("core.home"))
    form = RegisterForm(request.form)
    if form.validate_on_submit():
        user = User(email=form.email.data, password=form.password.data)
        db.session.add(user)
        db.session.commit()

        login_user(user)
        flash("You registered and are now logged in. Welcome!", "success")

        return redirect(url_for("core.home"))

    return render_template("accounts/register.html", form=form)

It's throwing an error in the register function at the second conditional on form.validate_on_submit(). I looked at the WTForms documentation, and from what I could understand, the validate() function is supposed to take an argument extra_validators. So I don't understand why it would be throwing this error.

Full disclosure, I was following a tutorial, and did compare my code to their final code and it matched.

What am I missing here?


Solution

  • You ignore that validate takes additional parameters. If you add this in your implementation it should work.

    def validate(self, extra_validators=None):
        initial_validation = super(RegisterForm, self).validate(extra_validators)
        # ...