SQLAlchemy Create All Table gives a NoReferencedTable Error - python

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)

Related

Save multiple media pictures for a value in database

I have a Table called property that accepts a contains column which refers to propertyContains table, then propertyContains will have a media column which refers to media table. i have no idea if i am storing the images the right way and i am wondering if there is any better/more efficient ways.
my code
class Property(Base):
__tablename__ = "property"
property_id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("propertyOwner.user_id"))
title = Column(String)
description = Column(String)
Location = Column(String)
rented = Column(Boolean)
rented_by = Column(Integer, ForeignKey("client.client_id"))
contains = relationship("PropertyContains", back_populates="contains_owner")
owner = relationship("Owner", back_populates="properties")
date = Column(Date, default=func.now())
class Config:
arbitrary_types_allowed = True
class Media(Base):
__tablename__ = "media"
media_id = Column(Integer, unique=True, primary_key=True, index=True)
media1 = Column(LargeBinary)
media2 = Column(LargeBinary)
media3 = Column(LargeBinary)
media_owner = Column(Integer, ForeignKey('propertyContains.property_contains_id', ondelete="CASCADE"))
class Config:
arbitrary_types_allowed = True
class PropertyContains(Base):
__tablename__ = "propertyContains"
property_contains_id = Column(Integer, unique=True, primary_key=True, index=True)
property_id = Column(Integer, ForeignKey("property.property_id"))
# media_id = Column(Integer, ForeignKey("media.media_id"))
bed_rooms = Column(Integer)
media = relationship("Media", backref="media", passive_deletes=True)
contains_owner = relationship("Property", back_populates="contains")
class Config:
arbitrary_types_allowed = True
please keep in note that i am a beginner <3.

Does anyone know how to fix "sqlalchemy.exc.AmbiguousForeignKeysError"?

sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join condition between parent/child tables on relationship Location.changes_in_location - there are multiple foreign key paths linking the tables. Specify the 'foreign_keys' argument, providing a list of those columns which should be counted as containing a foreign key reference to the parent table.
Someone else had asked about this error before, but the cause seems to have been different. I'm trying to track product movements between warehouses. This is the code for my models file:
from inventory import db
from datetime import datetime
class Product(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), unique=True, nullable=False)
product_movements = db.relationship('Movement', backref='item', lazy=True)
def __repr__(self):
return f"{self.name} added."
class Location(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), unique=True, nullable=False)
changes_in_location = db.relationship('Movement', backref='location', lazy=True)
def __repr__(self):
return f"{self.location} added."
class Movement(db.Model):
id = db.Column(db.Integer, primary_key=True)
product_id = db.Column(db.Integer, db.ForeignKey('product.id'))
product = db.Column(db.String(50), nullable=False)
from_location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
from_location = db.Column(db.String(50))
to_location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
to_location = db.Column(db.String(50))
quantity = db.Column(db.Integer, nullable=False)
timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
def __repr__(self):
return f"{self.quantity} units of {self.product} moved from {self.from_location} to {self.to_location} at {self.timestamp}."
You should be adding the relationship in models for multiply relation and specify the ForeignKey and primaryjoin in the relationship.
lass Location(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50), unique=True, nullable=False)
from_locations = db.relationship('Movement', backref='location', lazy=True, primaryjoin='Movement.from_location_id == Location.id')
to_location = db.relationship('Movement', backref='location', lazy=True, primaryjoin='Movement.to_location_id == Location.id')
def __repr__(self):
return f"{self.location} added."
class Movement(db.Model):
id = db.Column(db.Integer, primary_key=True)
product_id = db.Column(db.Integer, db.ForeignKey('product.id'))
product = db.Column(db.String(50), nullable=False)
from_location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
from_location = db.Column(db.String(50))
to_location_id = db.Column(db.Integer, db.ForeignKey('location.id'))
to_location = db.Column(db.String(50))
quantity = db.Column(db.Integer, nullable=False)
timestamp = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
from_location = db.relationship('Location', backref='from_locations', lazy=True, foreign_keys=[from_location_id])
to_location = db.relationship('Location', backref='to_locations', lazy=True, foreign_keys=[to_location_id])
def __repr__(self):
return f"{self.quantity} units of {self.product} moved from {self.from_location} to {self.to_location} at {self.timestamp}."

trying to get data from one table into another AttributeError: 'BaseQuery' object has no attribute

I'm trying to get the data from my show data into an artist.past_shows attribute. I'm using flask_sqlalchemy. I'm getting the error:
AttributeError: 'BaseQuery' object has no attribute 'past_shows'
I'm not quite sure how to do this. I'm trying to make the query like this:
artist = Artist.query.join(Artist.past_shows).filter(Artist.id==artist_id, Show.artist_id==artist_id)
These are my models:
class Venue(db.Model):
__tablename__ = 'venue'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String())
city = db.Column(db.String(120))
state = db.Column(db.String(120))
address = db.Column(db.String(120))
phone = db.Column(db.String(120))
image_link = db.Column(db.String(500))
facebook_link = db.Column(db.String(120))
seeking_talent = db.Column(db.Boolean, default=False)
seeking_description = db.Column(db.String())
genres = db.Column(db.ARRAY(db.String))
website = db.Column(db.String())
pastshows = db.relationship('Show', backref='pastshows', lazy=True)
class Artist(db.Model):
__tablename__ = 'artist'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
city = db.Column(db.String(120))
state = db.Column(db.String(120))
phone = db.Column(db.String(120))
genres = db.Column(db.ARRAY(db.String))
image_link = db.Column(db.String(500))
facebook_link = db.Column(db.String(120))
seeking_venue = db.Column(db.Boolean, nullable=False, default=False)
seeking_description = db.Column(db.String())
website = db.Column(db.String())
past_shows = db.relationship('Show', backref='past_shows', lazy=True)
class Show(db.Model):
__tablename__ = 'show'
id = db.Column(db.Integer, primary_key=True)
venue_id = db.Column(db.Integer, db.ForeignKey('venue.id'), nullable=False)
artist_id = db.Column(db.Integer, db.ForeignKey('artist.id'), nullable=False)
artist_name = db.Column(db.String())
venue_name = db.Column(db.String())
venue_image = db.Column(db.String())
start_time = db.Column(db.DateTime(), nullable=False)
How can I get the shows data for the artist_id I'm requesting into artist.past_shows?
1 - Change the column definition Venue.pastshows as following: pastshows = db.relationship('Show', back_populates='pastshows', lazy=True, primaryjoin="Show.venue_id==Venue.id")
2 - Change the column definition Artist.past_shows as following: past_shows = db.relationship('Show', back_populates='past_shows', lazy=True, primaryjoin="Show.artist_id==Artist.id")
3- Try to make a query like this: artist = Artist.query.join(Show, Artist.id==Show.artist_id).filter(Artist.id==artist_id, Show.artist_id==artist_id)
I figured it out by creating a data object and putting the data in it using for loops.

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'

SQLAlchemy relationship error

I do have these 2 calsses als DB models trying to buidl a 1 to many relation:
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), index=True) #, unique=True)
firstname = db.Column(db.String(50))
lastname = db.Column(db.String(50))
bt_ids = db.relationship("BT", order_by="BT.id", backref="user")
class BT(db.Model):
__tablename__ = 'bt'
id = db.Column(db.Integer, primary_key=True)
bt_id = db.Column(db.String(255), unique=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
user = db.relationship("User", backref=db.backref('bt', order_by=id))
But I guess I do not really understand the way of setting up the relationships:
ArgumentError: Error creating backref 'user' on relationship 'User.bt_ids': property of that name exists on mapper 'Mapper|BT|bt'
Any ideas?
EDIT
I actually wanted to achive something like the example of SQLAlchemy
class User(Base):
__tablename__ = 'users'
id = Column(Integer, Sequence('user_id_seq'), primary_key=True)
name = Column(String(50))
fullname = Column(String(50))
password = Column(String(12))
**addresses = relationship("Address", order_by="Address.id", backref="user")**
def __repr__(self):
return "<User(name='%s', fullname='%s', password='%s')>" % (
self.name, self.fullname, self.password)
class Address(Base):
__tablename__ = 'addresses'
id = Column(Integer, primary_key=True)
email_address = Column(String, nullable=False)
user_id = Column(Integer, ForeignKey('users.id'))
**user = relationship("User", backref=backref('addresses', order_by=id))**
def __repr__(self):
return "<Address(email_address='%s')>" % self.email_address
There is already a FK relation between User and BT through user_id property so you can't create another relation named user in BT.
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), index=True) #, unique=True)
firstname = db.Column(db.String(50))
lastname = db.Column(db.String(50))
bts = db.relationship("BT", order_by="BT.id", backref="user")
class BT(db.Model):
__tablename__ = 'bt'
id = db.Column(db.Integer, primary_key=True)
bt_id = db.Column(db.String(255), unique=True)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
Now I got it...
This was wrong:
user = db.relationship("User", backref=db.backref('bt_ids', order_by=id))
Now it works!

Categories

Resources