Flask SQLalchemy order_by value joined from two Tables - python

Currently I cant figure out how to perform a proper join in SQLalchemy, I have two tables User and Roomeach room is submited by a user and that is why each room has a users_id as foreign key.
User has an attribute has_payed.
What I want is to query all rooms which are in a certain city (works fine) and then order these results by the User.has_payed value. It shall show first all rooms which belong to users who have has_payed == True.
What I am currently doing:
Room.query.join(Room.users_id).order_by(User.has_payed)
That are my tables:
class User(UserMixin, Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
username = Column(Text, nullable=False, unique=True)
password = Column(Text, nullable=False)
has_payed = Column(Boolean, default=False)
vorname = Column(Text, nullable=True)
nachname = Column(Text, nullable=True)
email_verified = Column(Boolean, default=False)
handynummer = Column(Text, nullable=True)
email = Column(Text, unique=True)
# foreign key
addresses = relationship('Room', back_populates="users")
class Room(Base):
__tablename__ = 'zimmer'
id = Column(Integer, primary_key=True)
art = Column(Text, nullable=False)
personen = Column(Integer, nullable=False)
preis = Column(Integer, nullable=False)
infofeld = Column(Text, nullable=False)
land = Column(Text, nullable=False)
bundesland = Column(Text, nullable=False)
stadt = Column(Text, nullable=False)
plz = Column(Text, nullable=False)
strasse = Column(Text, nullable=False)
hausnr = Column(Text, nullable=True)
zimmer_lat = Column(Float, nullable=False)
zimmer_lng = Column(Float, nullable=False)
# foreign key
users_id = Column(Integer, ForeignKey('users.id'))
users = relationship("User", back_populates="addresses")

It seems that this solved the issue, but I dont know how it knows that it has to join on Room.users_id == User.id
Room.query.join(User).order_by(desc(User.has_payed))

Related

Sqlalchemy bulk update for Postgresql db takes longer on staging than on local

I am a bit new to Sqlalchemy
My goal is to update a table using Sqlalchemy, the total number of entries in the live environment will be around 44k
But I have tried to run my code on 2k entries for test purposes.
The process of bulk update for 2k takes around 2-3secs on local whereas on staging it takes more than 400 secs
for chunk in range(0, len(news_dictionary), 100):
new = []
for index, all_clusters in enumerate(
news_dictionary[chunk:chunk + 100]):
for news_id in all_clusters['clusters']:
new.append({"id": news_id,
"cluster_id": uuids_list[index + chunk]})
local_session.bulk_update_mappings(Feeds_class, new)
local_session.commit()
whereas,
The DB is Postgres replicated master, Feeds_class is a table defined using sqlalchemy
, news_dictionary is a list of dictionaries, the goal of this for loop is to insert "cluster_id" wherever a news_id was found in the Feeds_class.
Feeds_class already has data but the cluster_id column is empty, hence the update command
here's the definition of my Feeds_class
class Feeds_class(Base):
__tablename__ = 'feeds1'
id = Column(INTEGER, nullable=False, primary_key=True)
text = Column(Text, nullable=True)
description = Column(Text, nullable=True)
url = Column(Text, nullable=True)
image = Column(Text, nullable=True)
slug = Column(Text, nullable=True)
jobid = Column(Text, nullable=True)
source = Column(Text, nullable=True)
source_url = Column(Text, nullable=True)
logo = Column(Text, nullable=True)
pagetype = Column(Text, nullable=True)
htmlpath = Column(Text, nullable=True)
favicon = Column(Text, nullable=True)
md5 = Column(Text, nullable=True)
is_headline = Column(BOOLEAN, nullable=False, default=False)
download_time = Column(FLOAT, nullable=True)
time = Column(FLOAT, nullable=True)
last_parse_time = Column(FLOAT, nullable=True)
expiry = Column(FLOAT, nullable=True)
genre = Column(ARRAY(TEXT), default=[], nullable=False)
created_at = Column(DateTime, nullable=False, default=datetime.utcnow)
updated_at = Column(DateTime, nullable=False, default=datetime.utcnow)
cluster_id = Column(UUID(as_uuid=True), ForeignKey(f'{cluster_table_name}.id')
the following is the cluster class which have a foreign key relation to the feeds
class Clusters_class(Base):
__tablename__ = cluster_table_name
# app_uuid = Column(u'_uuid', UUID(), primary_key=True)
id = Column(
UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
created_at = Column(
TIMESTAMP,
nullable=True,
default=datetime.utcnow())
created_at_timestamp = Column(Float, nullable=True)
clusters = Column(ARRAY(INTEGER),nullable=False)
news = relationship('Feeds_class', backref=cluster_table_name,
lazy='dynamic')
Base.metadata.create_all(engine)

FlaskSqlAlchemy multi join on multi table. ambiguous column name

I'm about a month into learning and working with SQLAlchemy. I've been working on troubleshooting this for several hours using previous posts on StackOverflow and reading SQLAlchemy docs. Even watched videos on Youtube.
Can anybody help me with creating a proper query? I think I need to alias the column name, but I haven't got that to work yet.
Thank you in advance
cdm_mapping = db.Table('cdm_mapping',
db.Column('product_id', db.ForeignKey('product.id'), primary_key=True),
db.Column('cdm_id', db.ForeignKey('CDM.id'), primary_key=True)
)
user_products = db.Table('user_products',
db.Column('user_id', db.ForeignKey('user.id'), primary_key=True),
db.Column('product_id', db.ForeignKey('product.id'), primary_key=True)
)
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
created_on = db.Column(db.DateTime, default=datetime.utcnow)
updated_on = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
username = db.Column(db.String(20), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
website = db.Column(db.String(120), nullable=True)
company = db.Column(db.String(120), nullable=True)
title = db.Column(db.String(60), nullable=True)
image_file = db.Column(db.String(25), nullable=False, default='default.jpg')
password = db.Column(db.String(60), nullable=False)
role = db.Column(db.String(60), nullable=True)
permission = db.Column(db.String(60), nullable=True)
status = db.Column(db.String(60), nullable=True)
products = db.relationship("Product", secondary=user_products, back_populates="users")
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
created_on = db.Column(db.DateTime, default=datetime.utcnow)
updated_on = db.Column(db.DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
product_name = db.Column(db.String(120), unique=True, nullable=False)
product_shortname = db.Column(db.String(25), nullable=True)
homepage = db.Column(db.String(200), nullable=True)
rating = db.Column(db.Float, nullable=True)
review_count = db.Column(db.Integer, nullable=True)
github = db.Column(db.String(120), nullable=True)
description = db.Column(db.String(15000), nullable=True)
logo_file = db.Column(db.String(120), nullable=False, default='default.jpg')
# Relationships
categories = db.relationship("Category", secondary=product_category, back_populates="products")
features = db.relationship("Feature", secondary=product_feature, back_populates="products")
cdm_elements = db.relationship("CDM", secondary=cdm_mapping, back_populates="products")
vendor_id = db.Column(db.Integer, db.ForeignKey('vendor.id'), nullable=True)
users = db.relationship("User", secondary=user_products, back_populates="products")
class CDM(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(30), unique=True, nullable=False)
description = db.Column(db.String(15000), nullable=True)
# Relationship
products = db.relationship("Product", secondary=cdm_mapping, back_populates="cdm_elements")
This is the query I constructed dozens of different ways.
user_id = 1
def get_toolkit_in_cdm(user_id):
query = db.session.query(CDM.name, Product.product_name, User.username).join(CDM.products).join(User.products).filter(User.id == user_id).all()
for product, cdm, user in query:
print(product, cdm, user)
I get this error.
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) ambiguous column name: product.product_name

sqlalchemy.exc.ArgumentError: Can't find property named "consumed" on mapped class Instances->instance in this Query

I have this query
self.session.query(Instances).options(joinedload('consumed')).outerjoin(Consumed).filter(
and_(
queryInstances.customer_id == customer_id,
queryInstances.purged == 'false'
)
)
that returns the following error:
sqlalchemy.exc.ArgumentError: Can't find property named "consumed" on mapped class Instances->instance in this Query.
And my classes are
Instances:
class Instances(Base):
__tablename__ = 'instance'
id = Column(UUID, primary_key=True, server_default=FetchedValue())
coupon_id = Column(UUID, ForeignKey(Coupon.id), nullable=False)
customer_id = Column(TEXT, nullable=False)
created_at = Column(TIMESTAMP, nullable=False, server_default=FetchedValue())
reference = Column(TEXT, nullable=False)
offline_data = Column(TEXT, nullable=False)
purged = Column(BOOLEAN, nullable=False)
customer_info = Column(JSONB)
locked_for = Column(TEXT)
locked_until = Column(TIMESTAMP)
expires_at = Column(TIMESTAMP)
coupon = relationship(Coupon, lazy='joined')
and Consumed:
class Consumed(Base):
__tablename__ = 'consumed'
id = Column(UUID, primary_key=True, server_default=FetchedValue())
instance_id = Column(UUID, ForeignKey(Instances.id), nullable=False)
consumed_at = Column(TIMESTAMP, nullable=False, server_default=FetchedValue())
pos_id = Column(TEXT, nullable=False)
instance = relationship(Instances, backref=backref('consumed', uselist=False), lazy='joined')
Why I'm getting this error?
SQLAlchemy version 1.4

Flask - relationship with two tables

I'm trying to create a one to many relationship between two tables and I am having some issues with that.
Tables code
class Movies(db.Model):
__tablename__ = 'movies'
id = db.Column(db.String(300), primary_key=True)
cat_id = db.relationship('Category', backref='movie')
title = db.Column(db.String(250), nullable=False)
link = db.Column(db.String(250), nullable=False)
duration = db.Column(db.String(250), nullable=False)
thumb_large = db.Column(db.String(250), nullable=False)
thumb = db.Column(db.String(250), nullable=False)
embed = db.Column(db.String(250), nullable=False)
tags = db.Column(db.String(250), nullable=False)
published = db.Column(db.String(250), nullable=False)
class Category(db.Model):
__tablename__ = 'category'
id = db.Column(db.String(300), db.ForeignKey('movies.cat_id'), primary_key=True)
category = db.Column(db.String(30), nullable=False)
I'm trying to migrate it but it give me this error sqlalchemy.exc.NoReferencedColumnError: Could not initialize target column for ForeignKey 'movies.cat_id' on table 'category': table 'movies' has no column named 'cat_id'
I can't understand why this is happening if I already set the relationship.
Any idea what should I do?
I think that should fix it.
In my opinion the documentation of SQLAlchemy regarding relationships is very helpful. You can find this here.
class Movie(Model):
__tablename__ = 'movies'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(255), nullable=False, unique=True, index=True)
link = db.Column(db.String(255), nullable=False)
duration = db.Column(db.String(255), nullable=False)
thumb_large = db.Column(db.String(255), nullable=False)
thumb = db.Column(db.String(255), nullable=False)
embed = db.Column(db.String(255), nullable=False)
tags = db.Column(db.String(255), nullable=False)
published = db.Column(db.String(255), nullable=False)
cat_id = db.Column(db.Integer, ForeignKey('categories.id'))
category = db.relationship('Category', backref='movies')
class Category(Model):
__tablename__ = 'categories'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(31), nullable=False, unique=True, index=True)
Here is my clinic relationship between the patient and patient-detail, this might help you, and it does work for me.
class Patient(db.Model, UserMixin):
__bind_key__ = 'patient'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(10), nullable=False)
number = db.Column(db.String(11), unique=False, nullable=False)
gender = db.Column(db.String(10), nullable=False)
birth = db.Column(db.String(20), nullable=False)
IDcard = db.Column(db.String(12), nullable=False)
age = db.Column(db.String(3), unique=False, nullable=False)
create = db.Column(db.DateTime, nullable=False, default=datetime.now)
details = db.relationship('Detail', backref='patient', lazy=True)
class Detail(db.Model, UserMixin):
__bind_key__ = 'detail'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(20), unique=False, nullable=False)
Symptom = db.Column(db.String(100), nullable=False)
Initial_diagnosis = db.Column(db.String(50), nullable=False)
Preliminary_treatment_plan = db.Column(db.String(100), nullable=False)
Check_result = db.Column(db.String(50), nullable=False)
Patient_reason = db.Column(db.String(100), unique=False, nullable=False)
Doctor_name = db.Column(db.String(20), unique=False, nullable=False)
Date_of_diagnosis = db.Column(db.DateTime, nullable=False, default=datetime.now)
detail = db.Column(db.Integer, db.ForeignKey('patient.id'), nullable=False)
date_add = db.Column(db.DateTime, nullable=False, default=datetime.now)

How to attach User model with two different Models so that the properties of those models can be accessed via current_user

I am building a online quiz app where both teacher and students can login. Teachers can create quizzes and students can run those quizzes. How can I attach both Teacher and Student model with User model so that properties like Teacher_Name or Student_Class etc can be accessed via current_user?
This is not a problem regarding user role. Because using flask-security I can do that pretty easily but providing role means grouping users by their access level but not actually identifying them. I mean if a student logs in I need know who is this particular student represented by the current logged in user. Only then I can store his/her result with his/her record.
Followings are my sqlalchemy models...
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(120), unique=True, nullable=False)
password = db.Column(db.String(60), nullable=False)
class Student(db.Model):
__tablename__ = 'student'
id = db.Column(db.Integer, primary_key=True)
cls = db.Column(db.String(4), nullable=False, default='V')
sec = db.Column(db.String(1), nullable=False, default='A')
roll = db.Column(db.Integer, nullable=False, default=1)
name = db.Column(db.String(24), nullable=False)
dob = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
sex = db.Column(db.Enum(Gender), nullable=False, default=Gender.male)
results = db.relationship('Result', backref='student', lazy=True)
__table_args__ = (db.UniqueConstraint("cls", "roll", name="cls_roll"),)
class Teacher(db.Model):
__tablename__ = 'teacher'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(24), nullable=False)
subject = db.Column(db.String(4), nullable=False)
quiz_ques = db.Table('quiz_ques', db.Column('quiz_id', db.Integer, db.ForeignKey('quiz.id'), nullable=False),
db.Column('mcq_id', db.Integer, db.ForeignKey('mcq.id'), nullable=False),
db.PrimaryKeyConstraint('quiz_id', 'mcq_id'))
class Quiz(db.Model):
__tablename__ = 'quiz'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(50), nullable=False, unique=True)
subject = db.Column(db.String(4), nullable=False)
marks = db.Column(db.Integer, nullable=False, default=1)
time_limit = db.Column(db.Integer, nullable=False, default=20)
questions = db.relationship('MCQ', secondary=quiz_ques, lazy='subquery', backref=db.backref('quizzes', lazy=True))
results = db.relationship('Result', backref='quiz', lazy=True)
class MCQ(db.Model):
__tablename__ = 'mcq'
id = db.Column(db.Integer, primary_key=True)
subject = db.Column(db.String(4), nullable=False)
topic = db.Column(db.String(150), nullable=False)
question = db.Column(db.String(255), nullable=False)
answers = db.Column(db.Text(), nullable=False)
class Result(db.Model):
__tablename__ = 'result'
id = db.Column(db.Integer, primary_key=True)
date_created = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
marks_obtained = db.Column(db.Integer, nullable=False, default=0)
response = db.Column(db.Text(), nullable=True)
stud_id = db.Column(db.Integer, db.ForeignKey('student.id'), nullable=False)
quiz_id = db.Column(db.Integer, db.ForeignKey('quiz.id'), nullable=False)
The code should allow me to do something like this -
current_user.student.name = 'John Doe'
or
current_user.teacher.subject = 'Math'

Categories

Resources