StatementError: SQLite Date type only accepts Pyth

2019-08-27 02:20发布

问题:

I am using Flask-Security, the code seems fine, but when inserting a data from register view it gives the bellow error. Since I made SECURITY_TRACKABLE = True I added some extra fields in my models and the problem might be there :(

sqlalchemy.exc.StatementError
StatementError: SQLite Date type only accepts Python date objects as input. 
(original cause: TypeError: SQLite Date type only accepts Python date objects as input.) 
'INSERT INTO user (name, surname, email, password, birth_date, active, confirmed_at, last_login_at, current_login_at, last_login_ip, current_login_ip, login_count) 
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' [{'surname': u'Example', 'name': u'Test',
'confirmed_at': None, 'login_count': None, 'last_login_ip': None, 'active': True,
'last_login_at': None, 'current_login_at': None, 'birth_date': u'1989-04-27', 
'password': '$6$rounds=100000$yvVNKKdF5OFZY4Ur$bOpszUhnYVeMkY1fNwkjEcsA.BzOGCyelnPq9eKqmJFoTJ52Zd5cngYDqFQaPTZwSHoFq851IWGbl/gTqEUC1.', 
'email': u'test@test.com', 'current_login_ip': None}]

here is the form that I wrote to extend my RegisterForm:

from wtforms.validators import Required
from werkzeug.security import generate_password_hash, \
     check_password_hash

# to override the default RegisterForm
from flask_security.forms import RegisterForm, ConfirmRegisterForm, Form,\
                        TextField, BooleanField, \
                        PasswordField, validators

from flask.ext.security import Security, SQLAlchemyUserDatastore

class LoginForm(Form):
    """this class is used for user
     access to the  web application""" 

    username = TextField('username', 
        validators = [Required()])
    password = PasswordField('password', 
        validators = [Required()])
    remember_me = BooleanField('remember_me', default = False)

    #unhash the password
    def password_unhash(self, hashed_passw, submited_passw):
        return check_password_hash(hashed_passw, submited_passw)

class ExtendedConfirmRegisterForm(ConfirmRegisterForm):
    name  = TextField('Name', 
                    [validators.Length(max=255), 
                    validators.Required()])

    surname = TextField('Surname', 
                        [validators.Length(max=255)])
    birth_date = TextField('Date of birth', 
                        [validators.Length(max=10)])

class ExtendedRegisterForm(RegisterForm):
    """RegisterForm class needed for retrieving data from user"""
    #returns false if the email exists
    def email_unique(self, email):
        if models.User.query.\
            filter_by(email = email).\
            first() != None:
            self.email.errors.\
                append('This E-mail address is already in use. '
                        'Please choose another one.') 
            return False
        else:
            return True

this is my models.py:

from app import db
from flask.ext.security import UserMixin, RoleMixin

#association table that stores users and their roles
roles_users = db.Table('roles_users',
        db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
        db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))

#orm table that stores information on roles 
class Role(db.Model, RoleMixin):
    id = db.Column(db.Integer(), primary_key=True)
    name = db.Column(db.String(80), unique=True)
    description = db.Column(db.String(255))


class User(db.Model, UserMixin):
    """a class that used to create ORM Database and 
    objects related to the class"""

    id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String(255))
    surname = db.Column(db.String(255))
    email = db.Column(db.String(255), unique = True)
    password = db.Column(db.String(255))
    birth_date  = db.Column(db.Date)
    active = db.Column(db.Boolean())
    roles = db.relationship('Role', secondary=roles_users,
                            backref=db.backref('users', lazy='dynamic'))
    #SECURITY_CONFIRMABLE 
    confirmed_at = db.Column(db.DateTime())

    #SECURITY_TRACKABLE
    last_login_at = db.Column(db.DateTime())
    current_login_at = db.Column(db.DateTime())
    last_login_ip = db.Column(db.String(40))
    current_login_ip = db.Column(db.DateTime())
    login_count = db.Column(db.Integer(6))

回答1:

You have a birth_date column but used a text field in the form. Flask-Security uses WTForms for the form definitions; it has a dedicated DateField type which I think should be used instead:

from wtforms.fields import DateField

class ExtendedConfirmRegisterForm(ConfirmRegisterForm):
    name  = TextField('Name', 
                    [validators.Length(max=255), 
                    validators.Required()])

    surname = TextField('Surname', 
                        [validators.Length(max=255)])
    birth_date = DateField('Date of birth')