Retrieve all tables from sql-alchemy in flask - python

I was trying to get all the tables from the database whose Account=='Given Account'. But I wasn't able to fetch all the tables, only one table is getting fetched. Please help! Thank you!
#app.route('/user_account/', methods=['GET', 'POST'])
def user_account():
account = session['id']
transactions = Transaction.query.filter_by(Account=account).all()
return render_template('user_account.html',transactions=transactions)

You are calling the Transaction model object which will only give you results from the transactions table. If you are looking to return all tables the account is associated with you will need to import and call each object. For example:
orders = Order.query.filter_by(Account=account).all()
This would return all rows of orders that are associated with the account being queried. However this assumes you've set up your database model with relationship configurations. Ie your transaction model refers to the account being queried by with ForeignKey or Relationship:
class Transaction(db.Model):
__tablename__ = 'transactions'
id = db.Column(db.Integer, primary_key=True)
# Relationships.
user_id = db.Column(db.Integer, db.ForeignKey('users.id',
onupdate='CASCADE',
ondelete='CASCADE'),
index=True, nullable=False)

Related

SQLalchemy built relationship between classes

I am running into a conceptual problem I do not know how to approach, which might be due my lack of knowledge with SQLalchemy. I have two classes: People and Person and I want them each to have a column to share their respective id's with each other using the relationship function.
Now, I have an endpoint in views.py which instantiates those two classes and establishes a Child / Parent relationship. Looking at the database results however, only People, the parent class has the id stored in its respective table, while the Person table in column people is None.
I know the id in person is only generated after the commit() statement and thus None for Person, and was wondering if there is a way to solve this elegantly, or do I need to first query the current people instance, retreive its id, set the id in the person table and then commit() again?
I hope my question makes sense,thank you.
'''
model.py
'''
class People(Model):
__tablename__ = 'people'
id = Column(Integer, primary_key=True)
person = relationship('Person', back_populates='people')
person_id = Column(Integer, ForeignKey('people.id'))
class Person(Model):
__tablename__ = 'people'
id = Column(Integer, primary_key=True)
people = relationship('People', uselist=False, back_populates='person')
'''
views.py
'''
#main.route('/', methods=['GET', 'POST'])
def index():
people = People()
person = Person(people_id = ?)
people.person = person
session.add(person)
session.add(people)
session.commit()
I regret that I have not yet understood your question. However, since your code contains some errors, I will first write you my corrected variant.
class People(Model):
__tablename__ = 'people'
id = Column(Integer, primary_key=True)
person = relationship('Person', back_populates='people')
person_id = Column(Integer, ForeignKey('person.id'))
class Person(Model):
__tablename__ = 'person'
id = Column(Integer, primary_key=True)
people = relationship('People', back_populates='person')
def index():
person = Person()
people = People()
people.person = person
session.add(person)
session.add(people)
session.commit()
The question of gittert seems justified to me. It makes no sense to save the ForeignKey in both tables on the referenced identifiers of the other model.
What do you want to achieve?
If you're looking for an actual column in your database for your 'relationships', you won't find them. Your .people and .person are virtual relationships created in Python without any interaction with the SQL database.

How to ignore some models to migrate? [duplicate]

I am using Flask-SQLAlchemy to define my models, and then using Flask-Migrate to auto-generate migration scripts for deployment onto a PostgreSQL database. I have defined a number of SQL Views on the database that I use in my application like below.
However, Flask-Migrate now generates a migration file for the view as it thinks it's a table. How do I correctly get Flask-Migrate / Alembic to ignore the view during autogenerate?
SQL View name: vw_SampleView with two columns: id and rowcount.
class ViewSampleView(db.Model):
__tablename__ = 'vw_report_high_level_count'
info = dict(is_view=True)
id = db.Column(db.String(), primary_key=True)
rowcount = db.Column(db.Integer(), nullable=False)
Which means I can now do queries like so:
ViewSampleView.query.all()
I tried following instructions on http://alembic.zzzcomputing.com/en/latest/cookbook.html and added the info = dict(is_view=True) portion to my model and the following bits to my env.py file, but don't know where to go from here.
def include_object(object, name, type_, reflected, compare_to):
"""
Exclude views from Alembic's consideration.
"""
return not object.info.get('is_view', False)
...
context.configure(url=url,include_object = include_object)
I think (though haven't tested) that you can mark your Table as a view with the __table_args__ attribute:
class ViewSampleView(db.Model):
__tablename__ = 'vw_report_high_level_count'
__table_args__ = {'info': dict(is_view=True)}
id = db.Column(db.String(), primary_key=True)
rowcount = db.Column(db.Integer(), nullable=False)

Design patterns for flask API implementation

I am using flask with flask-restplus and sqlalchemy.
My rest API function looks like the following:
#ns.route('/user')
class UsersCollection(Resource):
#jwt_optional
#permissions.user_has('admin_view')
#ns.marshal_list_with(user_details)
def get(self):
"""
Returns list of users.
"""
users = User.query.all()
return users
I am willing to add additional data to users collection which should be returned by the API. Some of this data may be stored in other DB tables, while other is stored in memory.
What I am usually doing is something like this:
#ns.route('/user')
class UsersCollection(Resource):
#jwt_optional
#permissions.user_has('admin_view')
#ns.marshal_list_with(user_details)
def get(self):
"""
Returns list of users.
"""
users = User.query.all()
# Add additional data
for user in users:
user.activity = UserActivity.query ... # from DB
user.online_status = "Active" # Taken somewhere from memory
return users
Obviously I don't like this approach of adding data to the User object on the fly. But what is the best design pattern to achieve it?
About the design pattern, I recommend a DAO and Service approach, here's a good and short article about it:
https://levelup.gitconnected.com/structuring-a-large-production-flask-application-7a0066a65447
About the models User/Activity relationship, I presume you have a mapped Activity model. If this is a One to One relationship, in the User model create a activityId field for the FK field and a activity relation where your ORM (I'll assume SQLAlchemy) will retrieve when user.activity is accessed.
class Activity(db.Model):
id = db.Column(db.Integer, primary_key=True)
descrption = db.Column(db.String(255))
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
activity = db.relationship(Activity)
activityId = db.Column(db.Integer, db.ForeignKey(Activity.id))
If you have a Many to Many relationship you'll have to create a third class called ActivityUser to map the relation
class ActivityUser(db.Model):
id = db.Column(db.Integer, primary_key=True)
activity = db.relationship(Activity, lazy=True)
user = db.relationship(User, lazy=True)
activityId = db.Column(db.ForeignKey(Activity))
userId = db.Column(db.ForeignKey(User))
and you can retrieve the user activities like this (again assuming you use SQLAlchemy):
ActivityUser.query.filter(ActivityUser.userId == user.id).all()

No unique constraint matching given keys for referenced table "users" (PostgreSQL)

so I'm getting an error that no unique constraint matches given keys for one of my tables. I have two tables: Users and Items, of which we have a many-to-one relationship (many items for one user). I am using Flask-SQLAlchemy to do all of this:
class ItemModel(db.Model):
__tablename__ = 'items'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(40))
description = db.Column(db.String(80))
price = db.Column(db.Float(precision=2))
emailAddress = db.Column(db.String(40), db.ForeignKey('users.email'))
class UserModel(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer)
email = db.Column(db.String(40), primary_key=True)
name = db.Column(db.String(40))
last_name = db.Column(db.String(40))
items = db.relationship('ItemModel', lazy="dynamic")
To create the tables, I have this statement in my 'app.py':
#app.before_first_request
def create_database():
print("Creating tables.")
db.create_all()
The error is: no unique constraint matching given keys for referenced table users.
I am not sure where I'm going wrong since I have a foreign key in ItemModel that matches with the primary key in UserModel. Any suggestions/tips are welcome!
Thanks.
I actually got this to work - As Erwin Brandstetter mentioned above, the error occurred because you need to create the user tables first. In my case, I needed to update the user table in terms of the foreign key/primary key relationship on Postgres itself.
For the sake of someone who ends up here but they structured their code differently, say each entity is in it's own file, check your import order before calling the .create_all() method.
Here's how I like to get around the table ordering issue you're having:
table_names = ['users',
'items']
for table in table_names:
t = db.Model.metadata.tables[table]
t.create(bind=engine)

SQLAlchemy Object is already attached to session, then DetachedInstanceError on refresh, still adds to database

I'm having some trouble with making a Many-to-Many relationship in Flask using SQLAlchemy. I have my two models, and the relationship table. When I create a Group object, I want that group to have the user who creates the group as a member, and the user should have the group being created as a group.
However, when I submit the form to create the group, I get a InvalidRequestError, saying Object '<User at 0x7f85ad606a50>' is already attached to session '1' (this is '2')
Then, if I refresh the page, resubmitting the form, it successfully creates the group and database relationship. However, it shows a DetachedInstanceError, saying that Parent instance <User at 0x7f85ad606a50> is not bound to a Session; lazy load operation of attribute 'groups' cannot proceed. That error shows until I restart the server.
Relevant code:
db:
db = SQLAlchemy(app)
Models:
groups = db.Table('user_groups',
db.Column('group_id', db.Integer, db.ForeignKey('groups.id')),
db.Column('user_id', db.Integer, db.ForeignKey('users.id'))
)
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
groups = db.relationship('Group', secondary=groups,
backref=db.backref('members', lazy='dynamic'))
class Group(db.Model):
__tablename__ = 'groups'
id = db.Column(db.Integer, primary_key=True)
Attempting to add the group to the database:
g = Group()
db.session.add(g)
u = User.query.filter_by(googleID=session.get('id')).first()
g.members.append(u)
db.session.commit()
Any help is appreciated!
So I fixed it... The issue was that I was importing the database variable (db) into my model file. Apparently that's a no-no. So I just copy/pasted it into the main file.

Categories

Resources