flask sqlalchemy getting Unknown column error despite having them - python

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...

Related

Flask-SQLAlchemy relationship error (relation "table_name" does not exist)

I'm trying to make a foreign key (one-to-many relationship) between User_Info table and the rest tables, but it gives me this error:
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.UndefinedTable)
relation "user_info" does not exist LINE 1: INSERT INTO user_info
(username, first_name, last_name, gend...
^
[SQL: INSERT INTO user_info (username, first_name, last_name, gender,
date_of_birth, profile_img_url) VALUES (%(username)s, %(first_name)s,
%(last_name)s, %(gender)s, %(date_of_birth)s, %(profile_img_url)s)
RETURNING user_info.id] [parameters: {'username': 'gohammedhl',
'first_name': 'Ameer', 'last_name': 'Farqad', 'gender': '1',
'date_of_birth': '2019-09-25', 'profile_img_url': 'bla bla'}]
(Background on this error at: http://sqlalche.me/e/f405)
And here are my tables:
class User_Info(UserMixin, db.Model):
__tablename__ = "user_info"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), nullable=False, unique=True)
first_name = db.Column(db.String(30), nullable=False)
last_name = db.Column(db.String(30), nullable=False)
gender = db.Column(db.String(2), nullable=False)
date_of_birth = db.Column(db.DATE, nullable=False)
profile_img_url = db.Column(db.String, nullable=True)
post = db.relationship("Posts", backref="post_author", lazy=True)
comment = db.relationship("Comments", backref="comment_author", lazy=True)
phone_number = db.relationship("User_Auth", backref="ph_no_owner", lazy=True)
class User_Auth(UserMixin, db.Model):
__tablename__ = "user_auth"
id = db.Column(db.Integer, primary_key=True)
phone_no = db.Column(db.String(100), nullable=False, unique=True)
password_hash = db.Column(db.String(300), nullable=False)
ph_no_owner_id = db.Column(db.Integer, db.ForeignKey("user_info.id"))
class Posts(db.Model):
__tablename__ = "posts"
id = db.Column(db.Integer, primary_key=True)
body = db.Column(db.String(150), nullable=False)
img_url = db.Column(db.String(400), nullable=True)
post_date = db.Column(db.DateTime, default=datetime.utcnow, nullable=False)
post_author_id = db.Column(db.Integer, db.ForeignKey("user_info.id"))
class Comments(db.Model):
__tablename__ = "comments"
id = db.Column(db.Integer, primary_key=True)
comment = db.Column(db.String(150), nullable=False)
comment_date = db.Column(db.DateTime, default=datetime.utcnow)
comment_author_id = db.Column(db.Integer, db.ForeignKey("user_info.id"))
Any ideas?
Thanks in advance!
I solved it!
It was lacking:
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = ("postgresql://postgres:PasswordHere#localhost/dbName")
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db = SQLAlchemy(app)
And:
with app.app_context():
db.create_all()
Though this code was in a seperate file created for creating stuff, but it didn't work properly until I put it in the same file of the tables above!

Access multiple database in SQLAlchemy

This is my code:
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////root/Desktop/Social_Network/users.db'
app.config['SQLALCHEMY_BINDS'] = {'posts': 'sqlite:////root/Desktop/Social_Network/posts.db'}
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(40), unique=True, nullable=False)
password = db.Column(db.String, nullable=False)
joined_at = db.Column(db.DateTime(),default =datetime.datetime.now)
is_hero = db.Column(db.Boolean(),default=False)
class Post(db.Model):
__bind_key__ = 'posts'
id = db.Column(db.Integer, primary_key=True)
user = db.Column(db.String(50))
post = db.Column(db.String(255))
score = db.Column(db.Integer, nullable=False)
downVotes = db.Column(db.Integer, nullable=False )
posted_time = db.Column(db.DateTime(),default =datetime.datetime.now)
upVotes = db.Column(db.Integer,nullable=False)
dict_ = {}
def get_all_users():
users_ = User.query.all()
global dict_
for user in users_:
dict_[user.email] = user.password
return dict_
I have connected multiple databases in SQLAlchemy. My problem is whenever I run :
users_ = User.query.all()
. It returns the User object, but after I run the change it to post, something like this:
post = Post.query.all()
It returns none. Any help regarding this issue?

Flask Foreign Key Constraint

I have an issue with foreign key in Flask.
My model is the following :
Model.py
class User(db.Model):
__tablename__ = "users"
__table_args__ = {'extend_existing': True}
user_id = db.Column(db.BigInteger, primary_key=True)
# EDIT
alerts = db.relationship('Alert', backref='user', lazy='dynamic')
def __init__(self, user_id):
self.user_id = user_id
class Alert(db.Model):
__tablename__ = 'alert'
__table_args__ = {'extend_existing': True}
alert_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
user_id = db.Column(db.BigInteger, db.ForeignKey('users.user_id'), nullable=False)
name = db.Column(db.String(ALERT_NAME_MAX_SIZE), nullable=False)
def __init__(self, user_id, name):
self.user_id = user_id
self.name = name
I am able to add some user, for example
a = User(16)
b = User(17)
db.session.add(a)
db.session.add(b)
db.session.commit()
and some alerts :
c = Alert(16, 'test')
d = Alert(17, 'name_test')
db.session.add(c)
db.session.add(d)
db.session.commit()
I have two issues with the foreign key :
First of all, when I try to modify the user_id alert, I am able to do it even if the user_id is not in the database
alert = Alert.query.get(1)
alert.user_id = 1222 # not in the database
db.session.commit()
and I am able to create a alert with an user_id not in the Database:
r = Alert(16223, 'test')
db.session.add(r)
I don't understand why they is no relationship constraint.
Thx,
So I find how to do it with this stackoverflow question , I find how to force foreign Key Constraint.
I juste add this in __init__.py and change nothing to models.py
#event.listens_for(Engine, "connect")
def _set_sqlite_pragma(dbapi_connection, connection_record):
if isinstance(dbapi_connection, SQLite3Connection):
cursor = dbapi_connection.cursor()
cursor.execute("PRAGMA foreign_keys=ON;")
cursor.close()
There is mistake in your code for initialisation of Alert class. You should use backref variable (which is 'user') instead of user_id while initializing Alert. Following code should work.
class User(db.Model):
__tablename__ = "user"
__table_args__ = {'extend_existing': True}
user_id = db.Column(db.BigInteger, primary_key=True)
alerts = db.relationship('Alert', backref='user', lazy='dynamic')
def __init__(self, user_id):
self.user_id = user_id
class Alert(db.Model):
__tablename__ = 'alert'
alert_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
user_id = db.Column(db.BigInteger, db.ForeignKey('user.user_id'), nullable=False)
name = db.Column(db.String(ALERT_NAME_MAX_SIZE), nullable=False)
def __init__(self, user, name):
self.user = user
self.name = name
It works as below:
>>> a = User(7)
>>> db.session.add(a)
>>> db.session.commit()
>>> b = Alert(a, 'test')
>>> db.session.add(b)
>>> db.session.commit()
>>> alert = Alert.query.get(1)
>>> alert.user_id
7
>>> alert.user
<app.User object at 0x1045cb910>
>>> alert.user.user_id
7
It does not allow you to assign variable like d = Alert(88, 'trdft')
I think you should read Flask SqlAlchemy's One-to-Many Relationships for more details.
If you are using SQLite, foreign key constraints are by default not enforced. See Enabling Foreign Key Support in the documentation for how to enable this.

Fetching a specific column from SQLAlchemy relationship

I need to allow a user block other users in my app. My problem occurs when I want to check if a user has been blocked by the current (logged-in user). How do I check if a particular user is in the blocked list of the current user? My models are below:
class User(db.Model):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
urid = Column(String(50), unique=True)
full_name = Column(String(100))
...
blockedlist = relationship('Blacklist', primaryjoin='Blacklist.user_id==User.id', back_populates='owner')
class Blacklist(db.Model):
__tablename__ = 'blacklist'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
blocked_id = Column(Integer, ForeignKey('users.id'))
date_blocked = Column(DateTime, default=func.now())
owner = relationship('User', primaryjoin='Blacklist.user_id==User.id', back_populates='blockedlist')
blocked = relationship('User', primaryjoin='Blacklist.blocked_id==User.id')
def __init__(self, user_id, blocked_id):
self.user_id = user_id
self.blocked_id = blocked_id
Basically, I want to check that a user's id is in the current user's list of blocked id
You can use .any on a relationship, like so:
alice = User(urid='alice', full_name='Alice')
bob = User(urid='bob', full_name='Bob')
session.add(Blacklist(owner=alice, blocked=bob))
session.commit()
bob_blocked_alice = (
session.query(User.blockedlist.any(blocked_id=alice.id))
.filter(User.id == bob.id)
.scalar()
)
print('Did Bob block Alice:', bob_blocked_alice)
alice_blocked_bob = (
session.query(User.blockedlist.any(blocked_id=bob.id))
.filter(User.id == alice.id)
.scalar()
)
print('Did Alice block Bob:', alice_blocked_bob)
As an aside, you can simplify your relationships using the foreign_keys parameter:
blockedlist = relationship('Blacklist', foreign_keys='Blacklist.user_id', back_populates='owner')
owner = relationship('User', foreign_keys=user_id, back_populates='blockedlist')
blocked = relationship('User', foreign_keys=blocked_id)

Can't seem to have the variable from another table - SQLAlchemy

I have these two classes but they cant seem to connect with each other. The error I get is :
OperationalError: (OperationalError) no such column: user_points.user_id
Any ideas why this is?
class User(db.Model):
__tablename__ = "user"
id = db.Column('user_id',db.Integer , primary_key=True)
username = db.Column(db.String(20), unique=True , index=True)
password = db.Column(db.String(20))
firstname = db.Column(db.String(20))
surname = db.Column(db.String(20))
email = db.Column(db.String(100))
dt_joined = db.Column(db.DateTime, default=db.func.now())
points_rel = db.relationship('User_points',backref='pointers',lazy='dynamic')
# User Points table
class User_points(db.Model):
__tablename__ = "user_points"
id = db.Column('user_points_id',db.Integer, primary_key = True)
user_id = db.Column('user_id',db.Integer, db.ForeignKey('user.user_id'))
fixture_id = db.Column('fixture_id',db.Integer, db.ForeignKey('fixture.fixture_id'))
fixture_prediction_id = db.Column('fixture_prediction_id',db.Integer, \
db.ForeignKey('fixture_prediction.fixture_id'))
points = db.Column('points',db.Integer)
Any ideas anyone??? This is doing my head in :(
At User class try to define like
points_rel = db.relationship('user_points',backref='user',lazy='dynamic')
instead of using table name over class name. Hope that will fix your issue.
OR
Check Out This code
class User(db.Model):
__tablename__ = "user"
id = db.Column(db.Integer , primary_key=True)
username = db.Column(db.String(20), unique=True , index=True)
password = db.Column(db.String(20))
firstname = db.Column(db.String(20))
surname = db.Column(db.String(20))
email = db.Column(db.String(100))
dt_joined = db.Column(db.DateTime, default=db.func.now())
points_rel = db.relationship('User_points', backref='user', lazy='dynamic')
# User Points table
class User_points(db.Model):
__tablename__ = "user_points"
id = db.Column(db.Integer, primary_key = True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
fixture_id = db.Column(db.Integer, db.ForeignKey('fixture.fixture_id'))
fixture_prediction_id = db.Column(db.Integer, \
db.ForeignKey('fixture_prediction.fixture_id'))
points = db.Column(db.Integer)
What I did was to drop the table and recreate it. It appears there was some issue with the metadata, the columns were there when I did .keys() although when I specifically named it in a select statement it couldnt find it. I cant explain why but dropping the table and recreating it worked.

Categories

Resources