SqlAlchemy Flask - association table with more than two columns - python

I am creating a shopping cart, for this I am using the following models in Flask:
line_item = db.Table('line_item',
db.Column('cart_id', db.Integer, db.ForeignKey('cart.id')),
db.Column('product_id', db.Integer, db.ForeignKey('product.id')),
db.Column('price', db.Float)
)
class Cart(db.Model):
id = db.Column(db.Integer, primary_key=True)
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.Unicode(64), index=True, unique=True)
description = db.Column(db.Unicode(500), index=True, unique=True)
image_url = db.Column(db.Unicode(128))
price = db.Column(db.Float)
line_item = db.relationship('Cart', secondary=line_item, backref=db.backref('products', lazy='dynamic'))
I want to use an extra column in the association table "line_item" to include price in order to save the price of a product at the moment the user adds it to the cart.
I know that without the price column I would do the following to add this data.
p = Product()
c = Cart()
p.line_item.append(c)
db.session.add(p)
db.session.commit()
How am I supposed to insert the price in the association table?

Use a db.Model for your LineItem - untested code as follows:
class LineItem(db.Model):
__tablename__ = 'line_items'
cart_id = db.Column(db.Integer, db.ForeignKey('carts.id'), primary_key=True)
product_id = db.Column(db.Integer, db.ForeignKey('products.id'), primary_key=True)
price = db.Column(db.Float)
cart = db.relationship("Cart", back_populates="line_items")
product = db.relationship("Product", back_populates="carts")
class Cart(db.Model):
__tablename__ = 'carts'
id = db.Column(db.Integer, primary_key=True)
line_items = db.relationship(LineItem, back_populates="cart")
class Product(db.Model):
__tablename__ = 'products'
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.Unicode(64), index=True, unique=True)
description = db.Column(db.Unicode(500), index=True, unique=True)
image_url = db.Column(db.Unicode(128))
price = db.Column(db.Float)
carts = db.relationship(LineItem, back_populates="product")
p = Product()
c = Cart()
line_item = LineItem()
line_item.price = p.price
line_item.product = p
c.line_items.append(line_item)

Related

sqlalchemy populate value based on relationship

I have two tables:
class Ticket(db.Model):
ticketID = db.Column(db.Integer, primary_key=True)
uidCreator = db.Column(db.Integer, db.ForeignKey("User.id"))
uidEmployee = db.Column(db.Integer, db.ForeignKey("User.id"))
ticketType = db.Column(db.String(50))
ticketComments = db.Column(db.String(500))
empTicketComments = db.Column(db.String(500))
empDateRespond = db.Column(db.DateTime(timezone=True))
empDateTaken = db.Column(db.DateTime(timezone=True))
dateCreated = db.Column(db.DateTime(timezone=True), default=func.now())
dateResolved = db.Column(db.DateTime(timezone=True))
Status = db.Column(db.String(24))
department =
And
class DepartmentTickets(db.Model):
id = db.Column(db.Integer(), primary_key=True)
department = db.Column(db.String(100))
ticketType = db.Column(db.String(100), unique=True)
How can I return the department for my Ticket.department column where Ticket.ticketType == DepartmentTickets.ticketType ?

Querying user specific data in flask

I'm building an app that shows a database of different plant species. Each user sees the same table of plant species except for the "notes" column, which each user can edit to their own liking. This is the database structure I have created:
class Note(db.Model):
__tablename__ = 'plantdatabasenote'
id = db.Column(db.Integer, primary_key=True)
content = db.Column(db.Text(), nullable=False)
plant_id = db.Column(db.Integer, db.ForeignKey("plant.id"))
user_id = db.Column(db.Integer, db.ForeignKey("profile.id"))
class Plant(db.Model):
__tablename__ = 'plant'
id = db.Column(db.Integer, primary_key=True)
common_name = db.Column(db.String(200), nullable=False)
date_created = db.Column(db.DateTime, default=datetime.utcnow)
notes = db.relationship("Note", backref="user_notes")
class Profile(db.Model):
__tablename__ = 'profile'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(200), unique=True, nullable=False)
I tried to retrieve the notes of user 1 with the following:
Plant.query.filter(Plant.notes.any(user_id=1)).all()
Unfortunately, this does not give me all the plants with the notes of user 1. Any idea how to fix this?

How to Perform filtering and sorting or filtering different column in Flask_SQLACLHEMY

I am creating a site where you can log in and then add your favorite animes and movies to your favorite list, for that I created a database and 3 tables User, Anime and Movie.
My database code:
from . import db
from flask_login import UserMixin
from sqlalchemy.sql import func
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(150), unique=True)
password = db.Column(db.String(150))
first_name = db.Column(db.String(150))
anime = db.relationship('Anime')
movie = db.relationship('Movie')
class Movie(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(50), nullable=False)
date = db.Column(db.DateTime(timezone=True), default=func.now())
year = db.Column(db.Integer, nullable=False)
description = db.Column(db.String(400), nullable=False)
rating = db.Column(db.Float, nullable=True)
ranking = db.Column(db.Integer, nullable=True)
review = db.Column(db.String(50), nullable=True)
img_url = db.Column(db.String(250), nullable=False)
movie_link = db.Column(db.String(250), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
class Anime(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(50), nullable=False)
year = db.Column(db.Integer, nullable=False)
date = db.Column(db.DateTime(timezone=True), default=func.now())
description = db.Column(db.String(400), nullable=False)
rating = db.Column(db.Float, nullable=True)
ranking = db.Column(db.Integer, nullable=True)
review = db.Column(db.String(50), nullable=True)
img_url = db.Column(db.String(250), nullable=False)
anime_link = db.Column(db.String(250), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
I want to first filter all the data with the current user id
(all_anime = Anime.query.filter_by(id=current_user.id.).all())
then sort them according to the ratings given by the user
(all_anime = Anime.query.order_by(Anime.rating).all())
all_anime = User.anime.query.order_by(Anime.rating).all()
all_anime = db.session.query(Anime).filter_by(id=current_user.id).all()
print(all_anime)
for i in range(len(all_anime)):
all_anime[i].ranking = len(all_anime) - i
db.session.commit()
I know this snippet of code is wrong but I want to perform two different functions in two different columns how can I do it.
I also wanted to not accept the anime titles which are already present in the list of that user.
for that purpose, I have to filter the data with that user id
(anime_name = Anime.query.filter_by(id=current_user.id).all())
and then filter the data with the anime title
(anime_name = Anime.query.filter_by(title=data['canonicalTitle']).first()))
#views.route("/anime/find")
def find_anime():
anime_api_id = request.args.get("id")
if anime_api_id:
movie_api_url = f"https://kitsu.io/api/edge/anime//{anime_api_id}"
response = requests.get(movie_api_url)
data = response.json()['data']['attributes']
name = data["canonicalTitle"].replace(' ', '%20')
description = data['description'].rsplit('.', 1)[0]
# anime_name = User.anime.query.filter_by(title=data['canonicalTitle']).first()
# if anime_name:
# flash("Anime Already exists In The List.", category="error")
# else:
new_anime = Anime(
title=data['canonicalTitle'],
year=data['startDate'].split("-")[0],
img_url=data['posterImage']['medium'],
description=description,
anime_link=ANIME_SEARCH + name,
user_id=current_user.id
)
db.session.add(new_anime)
db.session.commit()
flash("Successfully Added.", category="success")
return redirect(url_for("views.edit_anime", id=new_anime.id))

how to use primary and foreign keys in SQL ALchemy

I have the following two tables. User and Project.
I need User_ID and name to be projected in Project table columns user_ID and User respectively but i couldn't achieve it.
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
User_ID = db.Column(db.Integer, unique=True)
name = db.Column(db.String(20))
project = db.relationship('Project', backref='proj')
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
user = db.Column(db.String(50), db.ForeignKey("user.name"))
UserID = db.Column(db.Integer, db.ForeignKey("user.User_ID"))
customer = db.Column(db.String(50))
lead_office = db.Column(db.String(50))
phase = db.Column(db.String(50))
Try this ( it worked for me in similar project):
class User(db.Model):
User_ID = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(20))
class Project(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
id_user = db.Column(db.String(50), db.ForeignKey("User.User_ID"))
customer = db.Column(db.String(50))
lead_office = db.Column(db.String(50))
phase = db.Column(db.String(50))

Many to many query for objects

I have a many to many relationship and I'm trying to make a query to return one or all the objects but the max I can get is the id of that object which is the foreign key of my Association Class Table.
This is my association class table
class PolPropAssociation(db.Model):
__tablename__ = 'polprop'
politician = db.Column(db.Integer, db.ForeignKey('politics.idPolitician'), primary_key=True)
proposal = db.Column(db.Integer, db.ForeignKey('proposals.idProposal'), primary_key=True)
relation = db.Column(db.String(120))
parent = db.relationship("Politic", back_populates="children")
child = db.relationship("Proposal", back_populates="parents")
draft = db.Column(db.Boolean, default=True)
def __init__(self, relation):
self.relation = relation.title()
class Politic(db.Model):
__searchable__ = ['publicName', 'completeName']
__tablename__ = 'politics'
idPolitician = db.Column(db.Integer, primary_key=True)
publicName = db.Column(db.String(150))
completeName = db.Column(db.String(300))
startDate = db.Column(db.Date, default=datetime.datetime.utcnow)
endDate = db.Column(db.Date, default=datetime.datetime.utcnow)
positions=db.relationship('Position',backref='pos_politic',lazy='select')
draft = db.Column(db.Boolean, default = True)
biolink = db.Column(db.String(200))
flag = db.relationship('Flag', cascade="all, delete", backref='politics', lazy='dynamic')
children = db.relationship("PolPropAssociation", back_populates="parent", lazy='dynamic')
class Proposal(db.Model):
__tablename__ = 'proposals'
idProposal = db.Column(db.Integer, primary_key=True)
dateProposal = db.Column(db.Date, default=datetime.datetime.utcnow)
description = db.Column(db.String(500))
linkProposal = db.Column(db.String(200))
idCategory = db.Column(db.Integer, db.ForeignKey('category.idcategory'))
idProposalState = db.Column(db.Integer, db.ForeignKey('proposalstate.idproposalstate'))
draft = db.Column(db.Boolean, default = True)
flag = db.relationship('FlagProposal', backref='proposals', lazy='dynamic')
parents = db.relationship("PolPropAssociation", back_populates="child", lazy='dynamic')
And I want to return all the proposals of a politician with a given idProposal:
proposal = Proposal.query.filter_by(idProposal=idProposal).first()
politicians = proposal.parents.all()
but all it returns is an array with all the politician column of my Association Table. Is there any way I can return the Politic objects with those ids?
Best regards
I found the solution:
If there's anyone asking how to query something specific using an Object Association Table, here it goes:
pol = Politic.query.filter(Politic.children.any(proposal=idProposal)).all()

Categories