SqlAlchemy Entity class has no property when joining - python

I'm trying to do the following query:
stats = Session.query(PlayerMatchStats).join(Match, Match.id == PlayerMatchStats.match_id
).filter_by(player=self).order_by(Match.date.desc()).limit(5).all()
These are some parts of the relevant models:
class PlayerMatchStats(Base):
__tablename__ = 'players_stats'
id = Column(Integer, primary_key=True)
player_id = Column(ForeignKey('players.id'), index=True, nullable=False)
player = relationship('Player', backref='stats')
match_id = Column(ForeignKey('matches.id'), index=True, nullable=False)
match = relationship('Match', backref='players_stats')
team_id = Column(ForeignKey('teams.id'), index=True, nullable=False)
team = relationship('Team', backref='players_matches_stats')
class Match(Base):
__tablename__ = 'matches'
id = Column(Integer, primary_key=True)
league_id = Column(ForeignKey('leagues.id'), nullable=False, index=True)
home_team_id = Column(ForeignKey('teams.id'), nullable=False, index=True)
home_team = relationship('Team', foreign_keys=[home_team_id], backref='home_matches')
away_team_id = Column(ForeignKey('teams.id'), nullable=False, index=True)
away_team = relationship('Team', foreign_keys=[away_team_id], backref='away_matches')
class Player(Base):
__tablename__ = 'players'
id = Column(Integer, primary_key=True)
name = Column(String, nullable=False, index=True)
When trying to perform the query, the error I receive is: Entity '<class 'model.overview.Match'>' has no property 'player'

Sqlalchemy thinks that you're trying to filter based on a property on Match when you really need to filter on a property of PlayerMatchStats. You can explicitly tell SQLAlchemy which model you are referring to using the "filter" method instead of "filter_by". In summary:
stats = Session.query(PlayerMatchStats).join(Match, Match.id==PlayerMatchStats.match_id)\
.filter(PlayerMatchStats.player=self).order_by(Match.date.desc()).limit(5).all()
This is of course assuming that "self" is a Player object

Related

SQLAlchemy ORM: Mapping a non-unique column to schema

How would you map a column that is not unique and is not a key into another schema(table)?
class TaskEntity(Base, BaseMixin):
__tablename__ = "task_entity"
__table_args__ = (UniqueConstraint("dag_no", "ordinal_position", name="dag_ordinal_uq_constraint"),)
task_no = Column(BIGINT(20), primary_key=True, autoincrement=True, nullable=False)
job_no = Column(BIGINT(20), ForeignKey("job_tb.job_no"), nullable=False)
task_name = Column(String(128), unique=True, nullable=False)
ordinal_position = Column(SMALLINT(6), nullable=False, default=1)
ordinal_position is not unique on its own, but is unique per task_no which is unique per job_no.
Ex) job_no.A can only have 1 of task_no.A which can only have 1 of ordinal_position.C. But job_no.B can have a task_no.A and ordinal_position.C.
I am trying to create the below schema in conjunction with class TaskEntity above, but am returning a "errno: 150 "Foreign key constraint is incorrectly formed" which I am assuing comes from the fact that ordinal_position is not unique.
class TaskLog(Base, BaseMixin):
__tablename__ = "task_log"
task_log_no = Column(BIGINT(20), nullable=False, autoincrement=True, primary_key=True)
execution_datetime = Column(TIMESTAMP, nullable=False)
start_datetime = Column(TIMESTAMP, nullable=False)
duration = Column(Float, nullable=False)
job_no = Column(BIGINT(20), ForeignKey("job_tb.job_no"), nullable=False)
task_no = Column(BIGINT(20), ForeignKey("task_entity.task_no"), nullable=False)
task_name = Column(String(128), ForeignKey("task_entity.task_name"), nullable=False)
# this is the declaration causing issues:
task_ordinal_position = Column(SMALLINT(6), ForeignKey("task_entity.ordinal_position"), nullable=False)
Have tried using relationships and "primary_join=", but the mapping seems to be very off once the data comes in.
Any inputs, much appreciated.
If I'm reading this correctly, then you probably want a UniqueConstraint across all three columns:
__table_args__ = (
UniqueConstraint('task_no', 'job_no', 'ordinal_position'),
)

SqlAlchemy - two foreign keys and bidirectional relationship

I have a small base for a website for a real estate agency, below are two tables:
class Person(Base):
__tablename__ = "people"
id = Column(Integer, primary_key=True, index=True)
name = Column(String, nullable=False)
surname = Column(String, nullable=False)
city = Column(String, nullable=True)
# TODO - add lists
class Property(Base):
__tablename__ = "properties"
id = Column(Integer, primary_key=True, index=True)
city = Column(String, nullable=False)
address = Column(String, nullable=False)
owner_id = Column(Integer, ForeignKey("people.id"), nullable=False)
manager_id = Column(Integer, ForeignKey("people.id"), nullable=False)
# TODO - rework
owner = relationship("Person", foreign_keys=[owner_id], backref=backref("owners"))
manager = relationship("Person", foreign_keys=[manager_id], backref=backref("managers"))
I would like my 'Person' object to have two lists of properties - "owned_properites" and "properties_to_manage" (without losing reference to the owner/manager in the 'Property' class). But i don't know how to define a relationship to make auto mapping work properly.
If the class 'Property' only had one foreign key to the 'Person', for example - only "owner_id" key and "owner" object then it would be simple:
#in Property
owner_id = Column(Integer, ForeignKey("people.id"), nullable=False)
owner = relationship("Person", back_populates="property")
#in Person
owned_properties = relationship("Property", back_populates="owner")
But how to do the same with two keys, as shown at the beginning?

Sqlalchemy: How to manage multiple tables (Python)?

I need to create four tables. First table include the "Users", second include "Group Name", the second table should be related to "Users" table. Third table include "Groups Columns Data" which is related to "Group" table, and finally the fourth table is "Group Borrow Lending Data" which is also linked to third table i.e "Groups".
But it's throwing an error when I try to get specific username.
TypeError: sqlalchemy.exc.InvalidRequestError: Can't compare a
collection to an object or collection; use contains() to test for
membership.
#v1.get("/get-specific-groups/{group_name}", tags=["GROUP"])
def get_specific_groups(group_name: str, current_user: CreateGroupSchema = Depends(get_current_user), db: Session = Depends(get_db)):
return db.query(User, Group, GroupColumnsData).join(GroupColumnsData).filter(Group.owner_username == current_user.get("username")).all()
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
username = Column(String(60), unique=True, nullable=False)
email = Column(String(80), unique=True, nullable=False)
password = Column(String(140), nullable=False)
groups = relationship("Group", backref="owner")
class Group(Base):
__tablename__ = "groups"
id = Column(Integer, primary_key=True, index=True)
group_name = Column(String(60), unique=True, nullable=False)
description = Column(String, nullable=False)
owner_username = Column(String, ForeignKey("users.username"), default=User.username)
group_username = relationship("GroupColumnsData", backref="group_owner")
class GroupColumnsData(Base):
__tablename__ = "groupsColumnsData"
id = Column(Integer, primary_key=True, index=True)
payee_name = Column(String(60))
item_name = Column(String(100))
amount_spent = Column(Integer)
owner_group = Column(String, ForeignKey("groups.group_name"), default=Group.group_name)
class GroupBorrowLendingData(Base):
__tablename__ = "groupsBorrowLendingData"
id = Column(Integer, primary_key=True, index=True)
lender = Column(String(60))
money_borrowed = Column(Integer)
borrower = Column(String(60))
owner_group = Column(String, ForeignKey("groups.group_name"), default=Group.group_name)
The Following code worked!
#v1.get("/get-specific-groups/{group_name}", tags=["GROUP"])
def get_specific_groups(group_name: str, current_user: CreateGroupSchema = Depends(get_current_user), db: Session = Depends(get_db)):
return db.query(Group).filter(Group.owner_username == current_user.get("username")).filter(Group.group_name.match(group_name)).all()

SQLAlchemy Create All Table gives a NoReferencedTable Error

I am asking fask_sqlalchemy to create table for me. But I am getting a NoReferencedTable Error.
Here is the code for Models:
from db import db
class Artist(db.Model):
__tablename__ = 'artists'
ArtistId = db.Column(db.Integer, primary_key=True)
Name = db.Column(db.NVARCHAR(120))
class Album(db.Model):
___tablename__ = 'albums'
AlbumId = db.Column(db.Integer, primary_key=True)
Title = db.Column(db.NVARCHAR(160), nullable=False)
ArtistId = db.Column(db.ForeignKey('artists.ArtistId'), nullable=False, index=True)
artist = db.relationship('Artist')
class Employee(db.Model):
__tablename__ = 'employees'
EmployeeId = db.Column(db.Integer, primary_key=True)
LastName = db.Column(db.NVARCHAR(20), nullable=False)
FirstName = db.Column(db.NVARCHAR(20), nullable=False)
Title = db.Column(db.NVARCHAR(30))
ReportsTo = db.Column(db.ForeignKey('employees.EmployeeId'), index=True)
BirthDate = db.Column(db.DateTime)
HireDate = db.Column(db.DateTime)
Address = db.Column(db.NVARCHAR(70))
City = db.Column(db.NVARCHAR(40))
State = db.Column(db.NVARCHAR(40))
Country = db.Column(db.NVARCHAR(40))
PostalCode = db.Column(db.NVARCHAR(10))
Phone = db.Column(db.NVARCHAR(24))
Fax = db.Column(db.NVARCHAR(24))
Email = db.Column(db.NVARCHAR(60))
parent = db.relationship('Employee', remote_side=[EmployeeId])
class Genre(db.Model):
__tablename__ = 'genres'
GenreId = db.Column(db.Integer, primary_key=True)
Name = db.Column(db.NVARCHAR(120))
class MediaType(db.Model):
__tablename__ = 'media_types'
MediaTypeId = db.Column(db.Integer, primary_key=True)
Name = db.Column(db.NVARCHAR(120))
class Playlist(db.Model):
__tablename__ = 'playlists'
PlaylistId = db.Column(db.Integer, primary_key=True)
Name = db.Column(db.NVARCHAR(120))
tracks = db.relationship('Track', secondary='playlist_track')
class Customer(db.Model):
__tablename__ = 'customers'
CustomerId = db.Column(db.Integer, primary_key=True)
FirstName = db.Column(db.NVARCHAR(40), nullable=False)
LastName = db.Column(db.NVARCHAR(20), nullable=False)
Company = db.Column(db.NVARCHAR(80))
Address = db.Column(db.NVARCHAR(70))
City = db.Column(db.NVARCHAR(40))
State = db.Column(db.NVARCHAR(40))
Country = db.Column(db.NVARCHAR(40))
PostalCode = db.Column(db.NVARCHAR(10))
Phone = db.Column(db.NVARCHAR(24))
Fax = db.Column(db.NVARCHAR(24))
Email = db.Column(db.NVARCHAR(60), nullable=False)
SupportRepId = db.Column(db.ForeignKey('employees.EmployeeId'), index=True)
employee = db.relationship('Employee')
class Invoice(db.Model):
__tablename__ = 'invoices'
InvoiceId = db.Column(db.Integer, primary_key=True)
CustomerId = db.Column(db.ForeignKey('customers.CustomerId'), nullable=False, index=True)
InvoiceDate = db.Column(db.DateTime, nullable=False)
BillingAddress = db.Column(db.NVARCHAR(70))
BillingCity = db.Column(db.NVARCHAR(40))
BillingState = db.Column(db.NVARCHAR(40))
BillingCountry = db.Column(db.NVARCHAR(40))
BillingPostalCode = db.Column(db.NVARCHAR(10))
Total = db.Column(db.Numeric(10, 2), nullable=False)
customer = db.relationship('Customer')
class Track(db.Model):
__tablename__ = 'tracks'
TrackId = db.Column(db.Integer, primary_key=True)
Name = db.Column(db.NVARCHAR(200), nullable=False)
AlbumId = db.Column(db.ForeignKey('albums.AlbumId'), index=True)
MediaTypeId = db.Column(db.ForeignKey('media_types.MediaTypeId'), nullable=False, index=True)
GenreId = db.Column(db.ForeignKey('genres.GenreId'), index=True)
Composer = db.Column(db.NVARCHAR(220))
Milliseconds = db.Column(db.Integer, nullable=False)
Bytes = db.Column(db.Integer)
UnitPrice = db.Column(db.Numeric(10, 2), nullable=False)
album = db.relationship('Album')
genre = db.relationship('Genre')
media_type = db.relationship('MediaType')
class InvoiceItem(db.Model):
__tablename__ = 'invoice_items'
InvoiceLineId = db.Column(db.Integer, primary_key=True)
InvoiceId = db.Column(db.ForeignKey('invoices.InvoiceId'), nullable=False, index=True)
TrackId = db.Column(db.ForeignKey('tracks.TrackId'), nullable=False, index=True)
UnitPrice = db.Column(db.Numeric(10, 2), nullable=False)
Quantity = db.Column(db.Integer, nullable=False)
invoice = db.relationship('Invoice')
track = db.relationship('Track')
The errror that I get is
sqlalchemy.exc.NoReferencedTableError
sqlalchemy.exc.NoReferencedTableError: Foreign key associated with
column 'tracks.AlbumId' could not find table 'albums' with which to
generate a foreign key to target column 'AlbumId'
The albums table is there and it has AlbumId column as well.
I don't understand this error.
Need some help understanding what is causing this error.
i think you made a mistake in your Album class. You can't have
db.relationship(...)
and
db.Column(db.ForeignKey(...))
in the same class.
I think, your Artist and Album classes should look like this:
class Artist(db.Model):
__tablename__ = 'artists'
ArtistId = db.Column(db.Integer, primary_key=True)
Name = db.Column(db.NVARCHAR(120))
Albums = db.relationship('Album', backref="artist"))
# Instead of 'Albums', you can name it whatever you want.
# It's just a way to access albums from an artist.
class Album(db.Model):
___tablename__ = 'albums'
AlbumId = db.Column(db.Integer, primary_key=True)
Title = db.Column(db.NVARCHAR(160), nullable=False)
ArtistId = db.Column(db.ForeignKey('artists.ArtistId'), nullable=False, index=True)
Thanks to this, you will be able to access albums from an artist within the Artiste class and vice-versa.
Thereby, if you want to access albums from an artist, you can do something like this:
artist = Artist(...)
artist.Albums
# It will automatically return albums from this artist
and vice-versa.
I suggest you to watch these two videos :
https://www.youtube.com/watch?v=juPQ04_twtA (One-to-Many relationship)
https://www.youtube.com/watch?v=OvhoYbjtiKc (Many-to-Many relationship)

flask-sqlalchemy: joined tables and one result object

I am coming from a python-django and am trying to get a grasp on flask-SQLAlchemy:
class Author(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(128), nullable=False)
class Book(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(128), nullable=False)
author = db.Column(db.Integer, db.ForeignKey('author.id'), nullable=False)
I want to get a joined result list:
results = Book.query.filter(Author.name=='tom')
for result in results:
print(result.title, result.???.name)
How do I access the fields of the joined tables?
I figured it out:
class Book(db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(128), nullable=False)
author_id = db.Column(db.Integer, db.ForeignKey('author.id'), nullable=False)
author = relationship("Author")
I needed to add the line
author = relationship("Author")
to the model. It seems to be necessary to declare the relationship on the object level. I did miss this.
Now the line can be:
print(result.title, result.author.name)

Categories

Resources