I have 3 tables that I'm having trouble traversing. These consist of a CAR table, a LOCATION table, and a CARLOCATION table. Car holds car data, location holds location data, and the carlocation table sits in the middle, and links a car to its current location.
Using Flask and SQLAlchemy, I want the user to be able to search a car by ID, which links to the CarLocation table with a relationship, and the CarLocation table links to the Location table via a relationship as well. So Car -> CarLocation -> Location
However, when I'm calling Car.CarLocation.Location.Name, I'm getting an error saying:
File "D:\Documents\GitHub\car_share\karshare\views.py", line 370, in searchcar
CurrentLocation = SearchedCar.CarLocations.Location.Name
AttributeError: 'InstrumentedList' object has no attribute 'Location'
Anybody who could assist me would be a lifesaver!
My models.py looks like below:
class Car(db.Model):
__tablename__ = 'Car'
__table_args__ = {'schema': 'KarShare'}
CarID = db.Column(db.Integer, primary_key=True, server_default=db.text(
"nextval('\"KarShare\".\"Car_CarID_seq\"'::regclass)"))
Make = db.Column(db.String(64), nullable=False)
Model = db.Column(db.String(64), nullable=False)
Year = db.Column(db.Integer, nullable=False)
Odometer = db.Column(db.Integer, nullable=False)
CarType = db.Column(db.String(64), nullable=False)
NumSeats = db.Column(db.Integer, nullable=False)
FuelType = db.Column(db.String(64), nullable=False)
CostPerHour = db.Column(db.Float, nullable=False)
TransmissionType = db.Column(db.String(9), nullable=False)
Registration = db.Column(db.String(), nullable=False)
class CarLocations(db.Model):
__tablename__ = 'CarLocations'
__table_args__ = {'schema': 'KarShare'}
CarID = db.Column(db.ForeignKey('KarShare.Car.CarID'), primary_key=True,
nullable=False)
CurrentLocationID = db.Column(db.ForeignKey('KarShare.Location.LocationID'),
nullable=True)
Location = db.relationship("Location", backref="CarLocations",
lazy=True)
Car = db.relationship("Car", backref="CarLocations",lazy=True)
class Location(db.Model):
__tablename__ = 'Location'
__table_args__ = {'schema': 'KarShare'}
LocationID = db.Column(db.Integer, primary_key=True, server_default=db.text(
"nextval('\"KarShare\".\"Location_LocationID_seq\"'::regclass)"))
Name = db.Column(db.String(64), index=True, unique=True, nullable=False)
StreetAddress = db.Column(db.String(128), nullable=False)
City = db.Column(db.String(64), index=True, nullable=False)
State = db.Column(db.String(64), index=True, nullable=False)
Longitude = db.Column(db.Numeric(precision=9, scale=6), nullable=False)
Latitude = db.Column(db.Numeric(precision=8, scale=6), nullable=False)
CarSpaces = db.Column(db.Integer, nullable=False)
And the simple code causing the error:
SearchedCar = Car.query.filter_by(CarID=form.search.data).first()
Make = SearchedCar.Make
Model = SearchedCar.Model
Year = SearchedCar.Year
Odometer = SearchedCar.Odometer
CarType = SearchedCar.CarType
NumSeats = SearchedCar.NumSeats
FuelType = SearchedCar.FuelType
CostPerHour = SearchedCar.CostPerHour
TransmissionType = SearchedCar.TransmissionType
CurrentLocation = SearchedCar.CarLocations.Location.Name
Registration = SearchedCar.Registration
Thanks for any help you can give!
Car has a list of CarLocation via relationship:
- CurrentLocation = SearchedCar.CarLocations.Location.Name
+ if SearchedCar.CarLocations:
+ CurrentLocation = SearchedCar.CarLocations[0].Location.Name
Related
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?
I am trying to get the price value from my EVENTS class as an INT so that I can use it to make a booking by multiplying by the number of attendees for an event when I insert a new row in the booking table.
Tables in databse
class Event(db.Model):
__tablename__ = 'events'
id = db.Column(db.Integer, primary_key=True)
host = db.Column(db.String(80), nullable=False)
event_title = db.Column(db.String(80), nullable=False)
event_description = db.Column(db.String(80), nullable=False)
movie_name = db.Column(db.String(80), nullable=False)
movie_description = db.Column(db.String(80), nullable=False)
genre = db.Column(db.String(80), nullable=False)
movie_start_time = db.Column(db.Time(), nullable=False)
movie_end_time = db.Column(db.Time(), nullable=False)
classification = db.Column(db.String(80), nullable=False)
rating = db.Column(db.Integer(), nullable=False)
actors = db.Column(db.String(200), nullable=False)
directors = db.Column(db.String(200), nullable=False)
event_date = db.Column(db.Date(), nullable=False)
published_date = db.Column(db.Date(), nullable=False)
published_by = db.Column(db.String(80), nullable=False)
image = db.Column(db.String(60), nullable=False)
capacity = db.Column(db.Integer(), nullable=False)
address = db.Column(db.String(80), nullable=False)
status = db.Column(db.String(80), nullable=False)
price = db.Column(db.Integer(), nullable=False)
# ... Create the Comments db.relationship
# relation to call destination.comments and comment.destination
comments = db.relationship('Comment', backref='event')
class Booking(db.Model):
__tablename__ = 'bookings'
id = db.Column(db.Integer, primary_key=True, unique=True)
attendees = db.Column(db.Integer(), nullable=False)
total_price = db.Column(db.Integer(), nullable=False)
booked_at = db.Column(db.DateTime, default=datetime.now())
# foreign key
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
event_id = db.Column(db.Integer, db.ForeignKey('events.id'))
Code calling from Events table to get price and insert new row into Booking table
price = Event.query.with_entities(Event.price).filter_by(id = event)
user_name = User.query.with_entities(User.id).filter_by(name = current_user.name)
num_attendees = forms.attendees.data
print(num_attendees)
print(type(price))
booking = Booking(attendees=forms.attendees.data,
total_price= price * num_attendees,
user_id = user_name,
event_id = event)
#here the back-referencing works - comment.destination is set
# and the link is created
db.session.add(booking)
db.session.commit()
But I keep running into errors such as TypeError: unsupported operand type(s) for *: 'Row' and 'int'
Thank you
I am trying to query two tables, Hostel and Room by joining them then fetch Hostel.name where my Room.hostel_id == Hostel.id so that my final query has Room data and a name from Hostel class, the Hostel.name.
Below are my classes
Hostel
class Hostel(UserMixin, db.Model):
__tablename__ = "hostel"
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False, index=True, unique=True)
location = db.Column(db.String(300), nullable=False)
management = db.Column(db.String(300), nullable=False)
rooms = db.Column(db.String(100), nullable=False)
caretaker = db.Column(db.String(300), nullable=False)
contact = db.Column(db.String(10), nullable=False)
description = db.Column(db.Text, nullable=False)
Room
class Room(UserMixin, db.Model):
__tablename__ = "room"
id = db.Column(db.Integer, primary_key=True)
rent = db.Column(db.Integer)
deposit = db.Column(db.Integer)
amenities = db.Column(db.String(300), nullable=False)
size= db.Column(db.String(300), nullable=False)
status = db.Column(db.String(300), nullable=False)
hostel_id = db.Column(db.Integer,nullable = False)
I have the following lines of code that I've tried working with;
room_data = Room.query\
.join(Hostel, Room.id==Hostel.id)\
.add_columns(Hostel.name)\
.filter(Room.hostel_id == Hostel.id)
and
room_data = Room.query.join(Hostel).filter(Room.hostel_id == Hostel.id).order_by(Room.id.desc()).all()
Help me fix this so that my query has all the details from the Room table and a new column that is from the hostel table that has the respective hostel name
Thanks, y'all. I simply added a relationship and used a backref to get the fields from the parent table
Added the following to my room table;
hostel_id = db.Column(db.Integer, db.ForeignKey("hostel.id"), nullable=False)
hostel = db.relationship("Hostel", backref=db.backref("hostel"), lazy=True)
I am new using sqlAlchemy and having problem creating new tables, specially when it comes around 2 foreign keys pointing to 1 table:
class Offers(db.Model):
__tablename__ = 'offers'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
contact_ign = db.Column(db.String(100))
conversion_rate = db.Column(db.Float)
stock = db.Column(db.Integer)
create_date = db.Column(db.DateTime(timezone=True), default=func.now())
currency_pair = db.relationship('CurrencyPairs', backref='pair', lazy='dynamic')
class CurrencyPairs(db.Model):
__tablename__ = 'currency_pairs'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
league = db.Column(db.String(100))
pair_id = db.Column(db.Integer, db.ForeignKey('offers.id'))
want = db.relationship('Currency', backref='want', lazy='dynamic')
have = db.relationship('Currency', backref='have', lazy='dynamic')
class Currency(db.Model):
__tablename__ = 'currency'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(100), nullable=False)
poe_trade = db.Column(db.Integer, nullable=False)
poe_official = db.Column(db.String(10), nullable=False)
tier = db.Column(db.Integer, nullable=False)
want_id = db.Column(db.Integer, db.ForeignKey('currency_pairs.id'))
have_id = db.Column(db.Integer, db.ForeignKey('currency_pairs.id'))
The error I am getting is:
sqlalchemy.exc.InvalidRequestError: One or more mappers failed to initialize - can't proceed with initialization of other mappers. Triggering mapper: 'Mapper|CurrencyPairs|currency_pairs'. Original exception was: Could not determine join condition b
etween parent/child tables on relationship CurrencyPairs.want - 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 refe
rence to the parent table
I have try different things but I get same result.
What am I doing wrong?
Thanks In advance.
I know this is an old question, but I had the same problem. I hope to help others with the answer.
This issue is addressed in the sqlalchemy documentation.
https://docs.sqlalchemy.org/en/13/orm/join_conditions.html#handling-multiple-join-paths
class Offers(db.Model):
__tablename__ = 'offers'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
contact_ign = db.Column(db.String(100))
conversion_rate = db.Column(db.Float)
stock = db.Column(db.Integer)
create_date = db.Column(db.DateTime(timezone=True), default=func.now())
currency_pair = db.relationship('CurrencyPairs', backref='pair', lazy='dynamic')
class CurrencyPairs(db.Model):
__tablename__ = 'currency_pairs'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
league = db.Column(db.String(100))
pair_id = db.Column(db.Integer, db.ForeignKey('offers.id'))
want_currency = relationship("Currency", foreign_keys='[Currency.want_id]', back_populates="want_currency_pairs")
have_currency = relationship("Currency", foreign_keys='[Currency.have_id]', back_populates="have_currency_pairs")
class Currency(db.Model):
__tablename__ = 'currency'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(100), nullable=False)
poe_trade = db.Column(db.Integer, nullable=False)
poe_official = db.Column(db.String(10), nullable=False)
tier = db.Column(db.Integer, nullable=False)
want_currency_pairs = relationship(CurrencyPairs, foreign_keys="[Currency.want_id]", back_populates="want_currency")
have_currency_pairs = relationship(CurrencyPairs, foreign_keys="[Currency.have_id]", back_populates="have_currency")
The way you wrote the code, sqlalchemy can't really understand which relationship to choose, because you have 2 of the same relationship. So you have to describe to sqlalchemy that there are 2 relationships to the same table.
I have got two tables:
Announcements
AnnouncementsSchedule
Relationship is one(Announcements) to many(AnnouncementsSchedule) by keys:
Announcements.id = AnnouncementsSchedule.announcements_id
I tried to describe models in SQLAlchemy:
The first table is described as model:
class Announcements(db.Model):
__tablename__ = 'announcements'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(150), nullable=False)
text = db.Column(db.Text(), nullable=False)
category = db.Column(db.Integer(), nullable=False)
subcategory = db.Column(db.Integer(), nullable=False)
offer_type = db.Column(db.Integer(), nullable=False)
url = db.Column(db.String(150), nullable=True)
status = db.Column(db.Integer(), nullable=False)
#children = relationship("AnnouncementsSchedule", back_populates="announcements")
Second is:
class AnnouncementsSchedule(db.Model):
__tablename__ = 'announcements_schedule'
id = Column(Integer, primary_key=True)
week_day = db.Column(db.Integer(), nullable=True)
week_all = db.Column(db.Integer(), nullable=False)
time = db.Column(db.Time(), nullable=False)
announcement_id = Column(Integer, ForeignKey('announcements.announcements_id'))
What I do wrong?
You have a mistake in the column name (announcements doesn't have announcement_id ):
# announcement_id = Column(Integer, ForeignKey('announcements.announcements_id'))
# change to ->
announcement_id = Column(Integer, ForeignKey('announcements.id'))