Why am I getting InstrumentedAttribute instead of basequery - python

I have created two models in flask using flask_sqlalchemy as follows:
class Analytics(db.Model, IdMixin, ModelMixin):
__tablename__ = "analytics"
record_id = Column(Integer, ForeignKey("record.id"), nullable=True)
created_at = Column(TIMESTAMP, nullable=True)
updated_at = Column(TIMESTAMP, nullable=True)
class HitLog(db.Model, IdMixin, TimestampMixin, ModelMixin):
__tablename__ = "hit_logs"
record_id = Column(Integer, ForeignKey("record.id"), nullable=True)
url = Column(Text, nullable=False, default='')
ip = Column(String(100), nullable=False, default='0.0.0.0', index=True)
referer = Column(Text, nullable=False, default='')
source = Column(String(255), nullable=False, default='', index=True)
query = Column(Text, nullable=False, default='')
user_agent = Column(String(255), nullable=False, default='')
created_at = Column(TIMESTAMP, nullable=True, index=True)
updated_at = Column(TIMESTAMP, nullable=True, index=True)
deleted_at = Column(TIMESTAMP, nullable=True, index=True)
Both the models are created the same way but still when I check for type, I get different results:
print type(Analytics.query)
print type(HitLog.query)
Gives me:
<class 'flask_sqlalchemy.BaseQuery'>
<class 'sqlalchemy.orm.attributes.InstrumentedAttribute'>
Why is it so?

You have a column named query in HitLog.

Related

sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class

I am beginner trying to make a relational database in Flask project using SQLalchemy
This is the error that I am getting when I try to register a user:-
sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class Question->question, expression 'Answer' failed to locate a name ('Answer'). If this is a class name, consider adding this relationship() to the <class 'nothingness.models.Question'> class after both dependent classes have been defined.
DB relationships are:-
User (Many to Many) Table
User (1 to Many) Question
Question (1 to Many) Answer
Table (1 to Many) Question
Here are my codes
from datetime import datetime
from nothingness import db
members = db.Table(
"member",
db.Column("id", db.Integer, primary_key=True),
db.Column("table_id", db.Integer, db.ForeignKey("table.id")),
db.Column("user_id", db.Integer, db.ForeignKey("user.id")),
)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(25), unique=True, nullable=False)
name = db.Column(db.String(25), nullable=False)
email = db.Column(db.String(), unique=True, nullable=False)
image_file = db.Column(db.String(20), nullable=False, default="default.jpg")
password = db.Column(db.String(60), nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
member = db.relationship("Table", secondary=members, backref=db.backref("members", lazy=True))
prashna = db.relationship("Question", backref="user", lazy=True)
def __repr__(self):
return f"User('{self.name}', '{self.username}', '{self.email}', '{self.image_file}')db.Model"
class Table(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(25), nullable=False)
key = db.Column(db.String(5), nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
question = db.relationship("Question", backref="questions", lazy=True)
def __repr__(self):
return f"Table('{self.id}', '{self.name}', '{self.key}', {self.created_at})"
class Question(db.Model):
id = db.Column(db.Integer, primary_key=True)
question = db.Column(db.String(255), nullable=False)
asked_by = db.Column(db.Integer, db.ForeignKey("user.id"))
asked_to = db.Column(db.Integer, nullable=False)
answer = db.relationship("Answer", backref="question", lazy=True)
table = db.Column(db.Integer, db.ForeignKey("table.id"))
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
class Answer:
id = db.Column(db.Integer, primary_key=True)
points = db.Column(db.Integer)
answer = db.Column(db.String(255), nullable=False)
answered_by = db.Column(db.Integer, nullable=False)
table_id = db.Column(db.Integer, nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
question = db.Column(db.Integer, db.ForeignKey("question.id"))
def __repr__(self):
return f"Answer('{self.points}', '{self.answer}', '{self.created_at}')"
This error occurred because I forgot to subclass Answer with db.Model

sqlalchemy.exc.NoReferencedTableError: Foreign key could not find table

I have some models that i'd like to migrate, 2 of them are:
FamilyMember.py
class FamilyMember(db.Model):
__tablename__ = 'family_members'
id = db.Column(db.Integer, primary_key=True)
parent_id = db.Column(db.Integer, db.ForeignKey('users.id'))
name = db.Column(db.String(120), index=True)
email = db.Column(db.String(120), index=True, unique=True)
password = db.Column(db.String(128), nullable=False)
notification = db.Column(db.Boolean, default=True)
auto_ml = db.Column(db.Boolean, default=True)
photo = db.Column(db.String(128), nullable=True)
created_at = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
updated_at = db.Column(db.DateTime(timezone=True), server_default=db.func.now(), onupdate=db.func.now())
notifications = db.relationship('Notification', backref='family_members', lazy='dynamic')
And Notification.py
class Notification(db.Model):
__tablename__ = 'notifications'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
fm_id = db.Column(db.Integer, db.ForeignKey('family_members.id'))
text = db.Column(db.String(255))
read = db.Column(db.Boolean, default=False)
type = db.Column(db.Integer)
created_at = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
updated_at = db.Column(db.DateTime(timezone=True), server_default=db.func.now(), onupdate=db.func.now())
Regarding to this post, i have to explicitly state table name with __tablename__ = 'tablename', i've done that but it didn't work the way it supposed to and still got the error sqlalchemy.exc.NoReferencedTableError: Foreign key associated with column 'notifications.fm_id' could not find table 'family_members' with which to generate a foreign key to target column 'id'. What should i do?
You can use back_populates instead of backref in db.relationship()
class Notification(db.Model):
__tablename__ = 'notifications'
id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
fm_id = db.Column(db.Integer, db.ForeignKey('family_members.id'))
text = db.Column(db.String(255))
read = db.Column(db.Boolean, default=False)
type = db.Column(db.Integer)
created_at = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
updated_at = db.Column(db.DateTime(timezone=True), server_default=db.func.now(), onupdate=db.func.now())
family_members = db.relationship("FamilyMember", back_populates="notifications")
class FamilyMember(db.Model):
__tablename__ = 'family_members'
id = db.Column(db.Integer, primary_key=True)
parent_id = db.Column(db.Integer, db.ForeignKey('users.id'))
name = db.Column(db.String(120), index=True)
email = db.Column(db.String(120), index=True, unique=True)
password = db.Column(db.String(128), nullable=False)
notification = db.Column(db.Boolean, default=True)
auto_ml = db.Column(db.Boolean, default=True)
photo = db.Column(db.String(128), nullable=True)
created_at = db.Column(db.DateTime(timezone=True), server_default=db.func.now())
updated_at = db.Column(db.DateTime(timezone=True), server_default=db.func.now(), onupdate=db.func.now())
notifications = db.relationship("Notification", back_populates="family_member")

Can I use Python's Pygal module to visualize data from an SQLalchemy database?

How can I convince Pygal to pull data from 2 tables in an SQLAlchemy database?
These are my models:
class PlannedPost(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(30), nullable=False, default='planned')
category = db.Column(db.String(30), nullable=False, default=None)
name = db.Column(db.String(30), nullable=True)
planned_amount = db.Column(db.Float, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
date_period = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
comments = db.Column(db.Text, nullable=True)
def __repr__(self):
return f"Post('{self.title}, '{self.category}'\
, '{self.name}', '{self.planned_amount}'\
, '{self.date_period}', '{self.comments}')"
class ActualPost(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(30), nullable=False, default='actual')
category = db.Column(db.String(30), nullable=False, default=None)
actual_amount_name = db.Column(db.String(30), nullable=True)
actual_amount = db.Column(db.Float, nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
date_posted = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
comments = db.Column(db.Text, nullable=True)
def __repr__(self):
return f"ActualPost('{self.title}, '{self.category}'\
, '{self.actual_amount_name}', '{self.actual_amount}'\
, '{self.date_posted}', '{self.comments}')"
And this is what the route I dreamed up, which I know is wrong because it seems that Pygal can use only lists.
#posts.route("/graphing")
def graphing():
planned = PlannedPost.query
actual = ActualPost.query
graph = pygal.Bar()
graph.title = 'Planned Values vs Actual Values'
graph.x_labels = planned.title
graph.add('Planned', [planned.planned_amount])
graph.add('Actual', [actual.actual_amount])
graph_data = graph.render_data_uri()
return render_template('graphing.html', graph_data=graph_data)
The answer to the question is "yes". One can visualise data from a database using Pygal.
See this question for code example: Python Pygal chart pulling data from database not matching values to labels

Database tables generation using sqlalchemy

I'm currently trying to generate SQL tables using the sqlalchemy library.
I have two tables : t_volume and t_volume_snapshot
class Volume(...):
""" Represent a volume element"""
__tablename__ = "t_volume"
created_at = Column(DateTime, nullable=False)
deleted_at = Column(DateTime, nullable=False)
volume_id = Column(String(length=255), nullable=False, primary_key=True)
volume_name = Column(String(length=255), nullable=False)
volume_type = Column(String(length=255), nullable=False)
volume_disk_space = Column(Integer, nullable=False)
class VolumeSnapshot(...):
""" Represent a volume snapshot element"""
__tablename__ = "t_volume_snapshot"
created_at = Column(DateTime, nullable=False)
deleted_at = Column(DateTime, nullable=False)
volume_snapshot_id = Column(String(length=255), nullable=False, primary_key=True)
volume_snapshot_name = Column(String(length=255), nullable=False)
volume_id = Column(String(length=255), ForeignKey("t_volume.volume_id"))
I would like that a volume snapshot refers to a volume using the value volume_id. I tried to define the t_volume_snapshot.volume_id column as a ForeignKey pointing to t_volume.volume_id but all I get is
OperationalError: (OperationalError) (1005, "Can't create table 'db.t_volume_snapshot' (errno: 150)")
I'm not used to sqlalchemy and SQL in general so I'm probably missing something...
You should be able to do something like below
class Volume(...):
""" Represent a volume element"""
__tablename__ = "t_volume"
created_at = Column(DateTime, nullable=False)
deleted_at = Column(DateTime, nullable=False)
volume_id = Column(String(length=255), nullable=False, primary_key=True)
volume_name = Column(String(length=255), nullable=False)
volume_type = Column(String(length=255), nullable=False)
volume_disk_space = Column(Integer, nullable=False)
snapshots = relationship("VolumeSnapshot", back_populates="t_volume")
class VolumeSnapshot(...):
""" Represent a volume snapshot element"""
__tablename__ = "t_volume_snapshot"
created_at = Column(DateTime, nullable=False)
deleted_at = Column(DateTime, nullable=False)
volume_snapshot_id = Column(String(length=255), nullable=False, primary_key=True)
volume_snapshot_name = Column(String(length=255), nullable=False)
snapshot_volume_id = Column(String(length=255), ForeignKey("volume_id"))
This should establish a bidirectional connection.

Understanding Joins in SQLAlchemy?

I'm having a lot of trobule understanding how joins work in SQLAlchemy, or possibly SQL altogether.. The following code works, but only because of luck and trial and error. I am not sure why it is producing the desired result.
In this case I wanted to get a list of Students for the current Instructor, all the instructor and student keys are join in a association table.. like so..
class Stud(db.Model):
__tablename__ = 'stud'
id = db.Column(db.Integer, primary_key=True, nullable=False)
first_name = db.Column(db.String(64), nullable=True)
last_name = db.Column(db.String(64), nullable=True)
email = db.Column(db.String(64), nullable=True)
cell = db.Column(db.String(10), nullable=True)
home = db.Column(db.String(10), nullable=True)
birthday = db.Column(db.DateTime(), nullable=True)
handicap = db.Column(db.String(7), nullable=True)
years_playing = db.Column(db.String(7), nullable=True)
gender = db.Column(db.String(7), nullable=True)
opt_in = db.Column(db.Boolean, nullable=True)
profile = db.Column(db.Boolean, default=False)
user_id = db.Column(db.Integer, nullable=True)
stud_inst_link = db.Table('stud_inst_link',
db.Column('inst_id', db.Integer, db.ForeignKey('inst.id')),
db.Column('stud_id', db.Integer, db.ForeignKey('stud.id')))
class Inst(db.Model):
__tablename__ = 'inst'
id = db.Column(db.Integer, primary_key=True, nullable=False)
first_name = db.Column(db.String(64), nullable=True)
last_name = db.Column(db.String(64), nullable=True)
email = db.Column(db.String(64), nullable=True)
cell = db.Column(db.String(10), nullable=True)
home = db.Column(db.String(10), nullable=True)
email_sig = db.Column(db.String, nullable=True)
birthday = db.Column(db.DateTime, nullable=True)
tax_rate = db.Column(db.Integer, nullable=True)
opt_in = db.Column(db.Boolean, nullable=True)
profile = db.Column(db.Boolean, default=False)
user_id = db.Column(db.Integer, nullable=False)
studs = db.relationship('Stud', secondary=stud_inst_link,
backref=db.backref('students', lazy='dynamic'))
The code that finally produced the result I want was this;
inst_id = 20
studs = Stud.query.join(stud_inst_link).filter(stud_inst_link.c.inst_id == inst_id).all()
for x in studs:
print(x.first_name)
It gave me the list of every student in the association table who is linked with instructor with id 20. However my program looks like it will have plenty of these joins and before continuing I would love to have a better understand of what is actually happening here.
Any help would be much appreicated.

Categories