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

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.

Related

Flask-SQLAlchemy Multiple Databases to form a query

I am new to using Flask SQLAlchemy and I have a few questions on how can how can I link separate databases together to form a query.
I have 3 databases: User, Homework, Questions, where 1 user can have many homework and 1 homework can have many questions. I have made 3 separate .py files for the 3 classes and each file calls simple functions like query.all(), and some simple filtering.
I have previously learned MySQL and I am wondering how can I create an SQLAlchemy equivalent of the following query:
SELECT * FROM user, homework, questions
WHERE user.user_id = homework.user_id
AND homework.homework_id = questions.homework_id
My question is how do I go about achieving this? Do I make a new file and find a way to bind these databases together or is there a more optimal way of doing it?
Also, how do I go about retrieving aggregated function values? For instance, the average marks one would get for each homework.
User.py
class User(db.Model):
__tablename__ = 'user'
user_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(20), nullable=False)
Homework.py
class Homework(db.Model):
__tablename__ = 'homework'
homework_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
user_id= db.Column(db.Integer, nullable=False)
subject = db.Column(db.String(20), nullable=False)
Question.py
class Question(db.Model):
__tablename__ = 'question'
question_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
homework_id = db.Column(db.Integer, nullable=False)
marks = db.Column(db.Integer, nullable=False)
You can create relationships amongst your tables using the following
class User(db.Model):
__tablename__ = 'user'
user_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(20), nullable=False)
class Homework(db.Model):
__tablename__ = 'homework'
homework_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.user_id'), nullable=False)
subject = db.Column(db.String(20), nullable=False)
class Question(db.Model):
__tablename__ = 'question'
question_id = db.Column(db.Integer, primary_key=True, autoincrement=True)
homework_id = db.Column(db.Integer, db.ForeignKey('homework.homework_id'), nullable=False)
marks = db.Column(db.Integer, nullable=False)
Then you can access info from a given table using the following
insert your desired user_id in replace for xxx
user_object = User.query.filter_by(user_id=xxx).first()
username = user_object.username
user_id_value = user_object.user_id
homework_object = Homework.query.filter_by(user_id=user_id_value).first()
subject = homework_object.subject
homework_id_value = homework_object.homework_id
question_object = Question.query.filter_by(homework_id=homework_id_value).first()
marks = question_object.marks

Query a single table with relationship database Flask-SQLAlchemy

I've got three tables: User, Role, Department
I want to query all the user with selected following filters:
Department.name , Role.name and User.degree
I can't find a solution to this problem, any suggestion would be great!
Here's my models simplified:
class User(UserMixin, db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
password_hash = db.Column(db.String(128))
degree = db.Column(db.String(20),default=None)
department_id = db.Column(db.Integer, db.ForeignKey('departments.id'))
role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))
class Department(db.Model):
__tablename__ = "departments"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(sqlalchemy.types.NVARCHAR(100), unique=True)
user = db.relationship('User', backref='department',
lazy='dynamic')
class Role(db.Model):
__tablename__ = 'roles'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(sqlalchemy.types.NVARCHAR(100), unique=True)
users = db.relationship('User', backref='role',
lazy='dynamic')
session.query(User).filter(
User.department.has(name='some_name)).filter(
User.role.has(name='some_role')).filter(
User.degree == 'some_degree')
It's a simple query with joins. You can modify "department" with your department filter and "role" with the same. You should modify the select part (session.query(User.id)) with the fields you want.
users = (session.query(User.id).join(Department, Department.user == User.id).join(Role, Role.user == User.id).filter(Department.name=="department").filter(Role.name=="role").group_by(User.id))

SQLAlchemy query filter by field value in related table

I try to get devices which type is not 'TYPE_BLADE_SERVER'. Please help write a query. My solution which i try:
result = Device.query.filter(DeviceGroup.type != ModelType.TYPE_BLADE_SERVER).all()
Which doesnt filter device_group table becouse device_group renamed to device_group_1. Sql query from sqlalchemy:
SELECT * FROM device_group, device
LEFT OUTER JOIN device_model AS device_model_1 ON device_model_1.id = device.model_id
LEFT OUTER JOIN device_group AS device_group_1 ON device_group_1.id = device_model_1.group_id
WHERE device_group.type != % (type_1)s ; {'type_1': 'TYPE_BLADE_SERVER'}
Working solution but like sql hardcode:
result = Device.query.filter(text("device_group_1.type <> 'TYPE_BLADE_SERVER'")).all()
My models:
class Device(db.Model):
__tablename__ = 'device'
id = db.Column(db.Integer, primary_key=True)
hostname = db.Column(db.String, index=True)
model_id = db.Column(db.ForeignKey('device_model.id'), nullable=True)
model = db.relationship("DeviceModel", backref='devices', lazy='joined')
class DeviceModel(db.Model):
__tablename__ = 'device_model'
id = db.Column(db.Integer, primary_key=True)
group_id = db.Column(db.ForeignKey('device_group.id', ondelete='SET NULL'), nullable=True)
class DeviceGroup(db.Model):
__tablename__ = 'device_group'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False, unique=True)
height = db.Column(db.Integer, nullable=False)
models = db.relationship("DeviceModel", backref=backref("group", lazy="joined"), lazy='joined')
type = db.Column(sa.Enum(ModelType), nullable=False)
class ModelType(enum.Enum):
TYPE_BLADE_SERVER = 'TYPE_BLADE_SERVER'
TYPE_ENGINEERING_DEVICES = 'TYPE_ENGINEERING_DEVICES'
TYPE_DATA_STORAGE = 'TYPE_DATA_STORAGE'
You need not_
from sqlalchemy import not_
result = Device.query.filter(not_(DeviceGroup.type == ModelType.TYPE_BLADE_SERVER)).all()
or
result = Device.query.filter(~DeviceGroup.type == ModelType.TYPE_BLADE_SERVER)
Copy answer link here:
https://groups.google.com/forum/#!topic/sqlalchemy/8L1HWG7H27U|
Docs:
http://docs.sqlalchemy.org/en/latest/orm/loading_relationships.html#the-zen-of-joined-eager-loading

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

Unable to delete parent record in one to many relationship - Flask-SqlAlchemy

I've created to 3 simple model with flask-sqlalchemy with one to many relationship. Here is the code for models:
class UsersModel(BaseModel, UserMixin):
__tablename__ = 'user'
email = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
confirmed_at = db.Column(db.DateTime())
info = db.relationship('UserInfoModel', backref="user", cascade="all, delete" , lazy='dynamic')
notes = db.relationship('NotesModel', backref="owner", cascade="all, delete" , lazy='dynamic')
class UserInfoModel(db.Model):
__tablename__ = 'user_info'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
first_name = db.Column(db.String(55))
last_name = db.Column(db.String(55))
age = db.Column(db.Integer)
profession = db.Column(db.String(255))
class NotesModel(BaseModel):
__tablename__ = 'notes'
title = db.Column(db.String(255), nullable=False)
desc = db.Column(db.Text)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
I can insert and retrive relational data without any problem but when I'm trying to delete a user it should also delete notes & info rather it gives error and don't let me delete. Here is the error that I see: http://prntscr.com/ek5cx1
But if I delete notes & info and then try to delete user it works. It's doing the reverse. I tried using 'delete-orphan' but didn't worked. I have read the documentation and read some blog about it but nothing helps. Am I wrong about declaring the relation? If so please help me to implement this or help me to find error within my code.
Appriciate your help, Thanks
Update: After adding delete-orphan I can delete data from session but not form phpmyadmin.
i think you want your relationships defined opposite how you have them, so like this:
class UsersModel(BaseModel, UserMixin):
__tablename__ = 'user'
email = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
confirmed_at = db.Column(db.DateTime())
class UserInfoModel(db.Model):
__tablename__ = 'user_info'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
first_name = db.Column(db.String(55))
last_name = db.Column(db.String(55))
age = db.Column(db.Integer)
profession = db.Column(db.String(255))
user = db.relationship('User',uselist=False, cascade='all, delete-orphan',backref=db.backref('info', uselist=False))
class NotesModel(BaseModel):
__tablename__ = 'notes'
title = db.Column(db.String(255), nullable=False)
desc = db.Column(db.Text)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
user = db.relationship('User',uselist=False, cascade='all, delete-orphan',backref=db.backref('notes'.lazy='dynamic'))
use this way
cascade="all,delete"

Categories

Resources