Flask-sqlalchemy table user has no column named email_address - python

I am learning Flask and I am trying to add a user to my database and I get this error.
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) table user has no column named email_address
[SQL: INSERT INTO user (username, email_address, password_hash, budget) VALUES (?, ?, ?, ?)]
class User(db.Model):
id = db.Column(db.Integer(), primary_key=True)
username = db.Column(db.String(length=30), nullable=False, unique=True)
email_address = db.Column(db.String(length=50), nullable=False, unique=True)
password_hash = db.Column(db.String(length=60), nullable=False)
budget = db.Column(db.Integer(), nullable=False, default=1000)
items = db.relationship("Item", backref="owned_user", lazy=True)
This is my model.
class RegisterForm(FlaskForm):
username = StringField(label="Username:")
email_address = StringField(label="Email:")
password1 = PasswordField(label="Password:")
password2 = PasswordField(label="Confirm Pasword:")
submit = SubmitField(label="Create Account")
This is the form.
user_to_create = User(username=form.username.data,
email_address=form.email_address.data,
password_hash=form.password1.data)
db.session.add(user_to_create)
db.session.commit()
This is the part I create the user.

I guess I changed the name of the column at some point after I created the table. After deleting and recreating the table it fixed.

Related

FLASK-WTF update a unique column PYTHON/FLASK/SQLITE

The def clean_clean email isn't working. This function should do two things as shown by two ifs. The first checks if no changes have been made to the field and if no changes have been made validation doesn't start, this currently work. The second if should check if the email entered already exists and if so present a validation error message. As the second if doesn't if an exisitng email is entered this leads to SQL IntegrityError.
Model.py - table
class User(db.Model, TimestampMixin, UserMixin):
__tablename__ = 'user'
__table_args__ = {'extend_existing': True}
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(50), nullable=False, unique=True)
email = db.Column(db.String(80), nullable=False, unique=True)
password_hash = db.Column(db.String(128))
first_name = db.Column(db.String(20), nullable=False)
last_name = db.Column(db.String(20), nullable=False)
forms.py
class EditUserForm(FlaskForm):
first_name = StringField('First Name', validators=[DataRequired()])
last_name = StringField('Last Name', validators=[DataRequired()])
email = StringField('Email', validators=[DataRequired(), Email()])
password = PasswordField('Password', validators=[DataRequired()])
password2 = PasswordField(
'Repeat Password', validators=[DataRequired(), EqualTo('password')])
update = SubmitField('Update')
cancel = SubmitField('Cancel')
def clean_email(self):
cd = self.cleaned_data
email = cd(email=email.data)
# if email is not modified, so don't start validation flow
if self.instance.pk is not None and self.instance.email == email:
return cd
# check email is unique or not
if User.objects.filter(email=email).exists():
raise ValidationError("Email address already exists!".format(email))
return cd
SQL error when a existing email is entered
sqlite3.IntegrityError: UNIQUE constraint failed: user.email
In reference to this error listed:
sqlite3.IntegrityError: UNIQUE constraint failed: user.email
This means that you're trying to save a new entry into your 'user' table with an email that already exist. You must have the constraint in your models.py file that says something like
email = db.Column(db.String(120), unique=True, nullable=False)
If you want users to be able to save an email that's already being used by a different user, then you need to change this to...
email = db.Column(db.String(120), unique=False, nullable=False)
It's not clear to me what you're trying to do, but if you want to do a query to find if the email is in use by someone besides the current user, you could do something like this:
email_already_in_use_boolean = bool(db.session.query(User).filter(User.email==email.data).filter(User.id!=current_user_id).first())

Saving to table works first time but not second time results in error: NOT NULL constraint failed in sqlalchemy

I get the error (sqlite3.IntegrityError) NOT NULL constraint failed: quiz1.user_id when I try saving to my table a second time. The tables are defined in my models.py file as:
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
image_file = db.Column(db.String(20), nullable=False, default='default.jpg')
password = db.Column(db.String(60), nullable=False)
posts = db.relationship('Post', backref='author', lazy=True)
quiz = db.relationship('Quiz1', backref='author', uselist=False)
class Post(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(100), nullable=False)
date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
content = db.Column(db.Text, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
class Quiz1(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
q1ans = db.Column(db.String(20), nullable=False)
q2ans = db.Column(db.String(20), nullable=False)
q3ans = db.Column(db.String(20), nullable=False)
q4ans = db.Column(db.String(20), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
In my routes.py file I have
#posts.route("/quiz", methods=['GET', 'POST'])
#login_required
def taste_quiz():
form = QuizForm()
if form.validate_on_submit():
quiz = Quiz1(q1ans=form.q1ans.data, q2ans=form.q2ans.data, q3ans=form.q3ans.data, q4ans=form.q4ans.data,
author=current_user)
db.session.add(quiz)
db.session.commit()
flash('Your responses have been saved', 'success')
return redirect(url_for('main.home'))
return render_template('taste_quiz.html', form=form)
When I click submit on the quiz form for the first time, the code executes as expected. When I try to submit it again it gives me the NOT NULL constraint failed error:
sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed: quiz1.user_id
[SQL: INSERT INTO quiz1 (q1ans, q2ans, q3ans, q4ans, user_id) VALUES (?, ?, ?, ?, ?)]
[parameters: ('3', '4', '5', '6', None)]
(Background on this error at: http://sqlalche.me/e/13/gkpj)
If I delete the record manually from the database and then submit the quiz form again, it works as expected but then trying it another time causes it to fail again.
If there is more code that you need to see, please let me know and I will update the question.
Thanks in advance
I think it should be like that in your user model.
quiz = db.relationship('Quiz1', backref=db.backref('author', uselist=False))
You have implemented a one-to-many relationship and used uselist.
You have several Quiz1 records for one user.
But only one user record for a Quiz1 record.
Thus the variable "quiz" is a list and its counterpart "author" is not.
Which relationship you define depends on the table in which the ForeignKey is created. This defines the reference to which table is referred.
If the key is saved in the "quiz1" table and references a certain "user" entry, then a quiz object can only have one user as the author. But several quiz objects can have the same user id stored in the foreignkey column.

Flask Security updating password not working

I am trying to use flask-Security to change the password. Basically, there are no errors being thrown but the hash in my database is not updating. When creating the initial password, everything works fine.
However, when I try to update using the code in update.py the password isn't updating. I appreciate your insight. Thank you.
update.py
buyer = Buyers.query.filter_by(id=buyer_id).first()
buyer.password = generate_password_hash(form.password.data)
db.session.commit()
flash('Password has been updated')
models.py
class Buyers(db.Model, UserMixin):
__tablename__ = 'buyers'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(64), unique=True, index=True, nullable=False)
firstname = db.Column(db.String(64), index=True, nullable=False)
lastname = db.Column(db.String(64), index=True, nullable=False)
company = db.Column(db.Integer, db.ForeignKey('company.id'))
password_hash = db.Column(db.String(128))
def __init__(
self, email, firstname, lastname, company, password
):
self.email = email
self.firstname = firstname
self.lastname = lastname
self.company = company
self.password_hash = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.password_hash, password)
Not totally sure what you are trying to accomplish - but the code snippets have your User model with a field password_hash - not password. Flask-Security requires certain defined model names to work.
Not sure where you are getting check_password_hash() and generate_password_hash()....
The way Flask-Security updates password is:
user.password = hash_password(password)
_datastore.put(user)
_datastore.commit()
Oh - and I assume you are Flask-Security-Too (which is a maintained fork).....

sqlalchemy.exc.IntegrityError: UNIQUE constraint failed

sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) UNIQUE constraint failed: user.city
[SQL: INSERT INTO user (username, "accountName", city, email, avatar, password) VALUES (?, ?, ?, ?, ?, ?)]
[parameters: ('sunny123', 'sunny kumar', 'Tumkur', 'sunny#gmail.com', 'default.jpg', '$2b$12$n3eEOEBhJ7aVEA4wctQn4O37jEYdgI0N2jqhNKm7Giy7Y7hxwaZIS')]
(Background on this error at: http://sqlalche.me/e/gkpj)
My User Model is
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(20), unique = True, nullable = False)
accountName = db.Column(db.String(20), nullable = False)
city = db.Column(db.String(20), nullable = False)
email = db.Column(db.String(120), unique = True, nullable = False)
avatar = db.Column(db.String(20), nullable = False, default = 'default.jpg')
password = db.Column(db.String(60), nullable = False)
def __repr__(self):
return f"User('{self.username}', '{self.accountName}','{self.city}','{self.email}', '{self.avatar}')"`enter code here`
And My Route is
#app.route('/signup', methods = ['GET', 'POST'])
def signup():
if current_user.is_authenticated:
return redirect(url_for('home'))
form = SignUp()
if form.validate_on_submit():
hashed_password = bcrypt.generate_password_hash(form.password.data).decode('utf-8')
user = User(username = form.username.data, accountName = form.accountName.data, city = form.city.data, email = form.email.data, password = hashed_password)
db.session.add(user)
db.session.commit()
flash('Your account has been created, now you can Signin', 'success')
return redirect(url_for('signin'))
return render_template('signup.html', title = 'Sign Up', form = form)
whenever i am trying to add a user with city name eg: "abc" which is mentioned by a previous user then it is throwing an error, but in my User model unique = True is just for username.
SQLAlchemy as a library can be easily used for managing tables, even creating them, but only for once.
If you have had a unique city column previously, and you haven't changed it from the Database, it will keep reinforcing the unique constraint on the column.
Because for the database, it still has a unique constraint. You cannot remove the UNIQUE constraint using ALTER in SQLite.
Refer to this answer for recreating the database safely.

flask sqlalchemy getting Unknown column error despite having them

So... I'm trying to commit some sql from flask app inside, and the model code is as follows:
class User(UserMixin, db.Model):
__tablename__ = '_users'
id = db.Column(db.Integer, primary_key=True)
user_email = db.Column(db.VARCHAR(50), nullable=False, unique=True)
user_reg_date = db.Column(db.TIMESTAMP, nullable=False)
last_login = db.Column(db.TIMESTAMP, nullable=True)
passwd = db.Column(db.VARCHAR(80), nullable=True)
social_id = db.Column(db.VARCHAR(80), nullable=True, unique=True)
def __init__(self, user_email, passwd, social_id):
self.user_email = user_email
self.user_reg_date = current_time()
self.passwd = passwd
self.social_id = social_id
class Player(db.Model):
__tablename__ = '_players'
id = db.Column(db.Integer, primary_key=True)
player_unique_id = db.Column(db.Integer, unique=True)
user_id = db.Column(db.Integer, db.ForeignKey('_users.id'))
affiliated_crew_id = db.Column(db.Integer, db.ForeignKey('crew.id'))
player_nick = db.Column(db.VARCHAR(50), unique=True)
player_highscore = db.Column(db.Integer)
player_badge = db.Column(db.VARCHAR(100))
player_rank = db.Column(db.Integer)
def __init__(self, player_unique_id, user_id, affiliated_crew_id
, player_nick):
self.player_unique_id = player_unique_id
self.user_id = user_id
self.affiliated_crew_id = affiliated_crew_id
self.player_nick = player_nick
self.player_highscore = 0
self.player_badge = None
self.player_rank = 0
I already have the proper columns in the SQL(as I written these from pre-made tables) it's all correct.
the part committing the sql is as follows:
player = Player(player_unique_id=00000, user_id=user_num, affiliated_crew_id=crew_id
, player_nick=nick)
db.session.add(player)
db.session.commit()
and it's returning this:
sqlalchemy.exc.InternalError: (pymysql.err.InternalError) (1054, "Unknown column '_users.id' in 'field list'") [SQL: 'INSERT INTO _players (player_unique_id, user_id, affiliated_crew_id, player_nick, player_highscore, player_badge, player_rank) VALUES (%(player_unique_id)s, _users.id, %(affiliated_crew_id)s, %(player_nick)s, %(player_highscore)s, %(player_badge)s, %(player_rank)s)'] [parameters: {'player_unique_id': 84658, 'affiliated_crew_id': '1', 'player_nick': 'player', 'player_highscore': 0, 'player_badge': None, 'player_rank': 0}]
what am I doing wrong here? searching didn't help so far...
I was using raw User class to get the User.id, which kept returning None.
since User was my flask-login's user class I had to bring my user id by using current_user.id.
so fixing my user_num init, which had user_num = User.id to user_num = current_user.id fixed everything...
thank you everyone who looked into the problem...

Categories

Resources