I have a Artist model, and a Venue model, and they have a many-to-many relationship facilitated by the Show model (the shows indicate the artist, venue and date of the concert).
class Venue(db.Model):
__tablename__ = 'Venue'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, unique=True, nullable=False)
shows = db.relationship('Show', backref='venue', lazy=True)
class Artist(db.Model):
__tablename__ = 'Artist'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, unique=True, nullable=False)
shows = db.relationship('Show', backref='artist', 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)
start_time = db.Column(db.DateTime, nullable=False)
venue = db.relationship('Venue', back_populates='venue')
artist = db.relationship('Artist', back_populates='artist')
I'd like to have a query to get the venue name, artist name, and date of all upcoming shows so had in mind the following...
upcoming_shows = Show.query.filter_by(show.start_time >= datetime.now()).all()
...so that I can then access for example, upcoming_shows[0].Venue.name, upcoming_shows[0].Artist.name and upcoming_shows[0].start_time.
That query however returns the following:
sqlalchemy.exc.ArgumentError: Error creating backref 'venue' on
relationship 'Venue.shows': property of that name exists on mapper
'mapped class Show->Show'
Feel like I'm close but missing something fundamental!
Solved. I made the changes below to the code and it works now. It was rather straight-forward in the end, I simply had to ensure that the relationship names were unique :-\
class Venue(db.Model):
__tablename__ = 'Venue'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, unique=True, nullable=False)
venue_shows = db.relationship('Show', back_populates='venue', lazy=True)
class Artist(db.Model):
__tablename__ = 'Artist'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, unique=True, nullable=False)
artist_shows = db.relationship('Show', back_populates='artist', 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)
start_time = db.Column(db.DateTime, nullable=False)
venue = db.relationship('Venue', back_populates='venue_shows')
artist = db.relationship('Artist', back_populates='venue_artist')
Here is a general example for what you are looking for
class Association(Base):
__tablename__ = 'association'
left_id = Column(Integer, ForeignKey('left.id'), primary_key=True)
right_id = Column(Integer, ForeignKey('right.id'), primary_key=True)
extra_data = Column(String(50))
child = relationship("Child", back_populates="parents")
parent = relationship("Parent", back_populates="children")
class Parent(Base):
__tablename__ = 'left'
id = Column(Integer, primary_key=True)
children = relationship("Association", back_populates="parent")
class Child(Base):
__tablename__ = 'right'
id = Column(Integer, primary_key=True)
parents = relationship("Association", back_populates="child")
For more details check the documentation
Related
I am beginner trying to make a relational database in Flask project using SQLalchemy
This is the error that I am getting when I try to register a user:-
sqlalchemy.exc.InvalidRequestError: When initializing mapper mapped class Question->question, expression 'Answer' failed to locate a name ('Answer'). If this is a class name, consider adding this relationship() to the <class 'nothingness.models.Question'> class after both dependent classes have been defined.
DB relationships are:-
User (Many to Many) Table
User (1 to Many) Question
Question (1 to Many) Answer
Table (1 to Many) Question
Here are my codes
from datetime import datetime
from nothingness import db
members = db.Table(
"member",
db.Column("id", db.Integer, primary_key=True),
db.Column("table_id", db.Integer, db.ForeignKey("table.id")),
db.Column("user_id", db.Integer, db.ForeignKey("user.id")),
)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(25), unique=True, nullable=False)
name = db.Column(db.String(25), nullable=False)
email = db.Column(db.String(), unique=True, nullable=False)
image_file = db.Column(db.String(20), nullable=False, default="default.jpg")
password = db.Column(db.String(60), nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
member = db.relationship("Table", secondary=members, backref=db.backref("members", lazy=True))
prashna = db.relationship("Question", backref="user", lazy=True)
def __repr__(self):
return f"User('{self.name}', '{self.username}', '{self.email}', '{self.image_file}')db.Model"
class Table(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(25), nullable=False)
key = db.Column(db.String(5), nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
question = db.relationship("Question", backref="questions", lazy=True)
def __repr__(self):
return f"Table('{self.id}', '{self.name}', '{self.key}', {self.created_at})"
class Question(db.Model):
id = db.Column(db.Integer, primary_key=True)
question = db.Column(db.String(255), nullable=False)
asked_by = db.Column(db.Integer, db.ForeignKey("user.id"))
asked_to = db.Column(db.Integer, nullable=False)
answer = db.relationship("Answer", backref="question", lazy=True)
table = db.Column(db.Integer, db.ForeignKey("table.id"))
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
class Answer:
id = db.Column(db.Integer, primary_key=True)
points = db.Column(db.Integer)
answer = db.Column(db.String(255), nullable=False)
answered_by = db.Column(db.Integer, nullable=False)
table_id = db.Column(db.Integer, nullable=False)
created_at = db.Column(db.DateTime, nullable=False, default=datetime.utcnow)
question = db.Column(db.Integer, db.ForeignKey("question.id"))
def __repr__(self):
return f"Answer('{self.points}', '{self.answer}', '{self.created_at}')"
This error occurred because I forgot to subclass Answer with db.Model
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'))
#mapping class
class Billing(Base):
__tablename__ = 'billing'
id = Column(Integer, primary_key=True)
billingdate= Column(DateTime, nullable=False)
amt = Column(Integer, nullable=False)
rate = Column(Integer, nullable=False)
fk_cpid = Column(Integer, ForeignKey('company.cpid'))
#run
query = self.mssql_session.query(Billing.billingdate).all()
result
$83749283 => $83,749,283
how to insert symbol(,) at Billing.billingdate in ONLY SQLAlchemy level?
Replace, SubString?
from sqlalchemy.ext.hybrid import hybrid_property
class Billing(Base):
__tablename__ = 'billing'
id = Column(Integer, primary_key=True)
billingdate= Column(DateTime, nullable=False)
_amt = Column(Integer, nullable=False)
rate = Column(Integer, nullable=False)
fk_cpid = Column(Integer, ForeignKey('company.cpid'))
#hybrid_property
def amt(self):
return '${:,}'.format(self._amt)
Hopes, this code can help you.
I have two models in database like
class Base(object):
def __tablename__(self):
return self.__name__.lower()
id = Column(Integer, primary_key=True, nullable=False)
utc_time = Column(BigInteger, default=utc_time, onupdate=utc_time)
class EntityModel(Base):
__tablename__ = 'entities'
town_id = Column(Integer, ForeignKey('towns.id', ondelete='CASCADE'), nullable=False)
type = Column(Integer, nullable=False)
level = Column(Integer, nullable=False, default=Level.LEVEL_ONE)
energy = Column(Float, nullable=False, default=0)
x = Column(Integer, nullable=False)
y = Column(Integer, nullable=False)
class CommandModel(Base):
__tablename__ = 'commands'
entity_id = Column(Integer, ForeignKey('entities.id', ondelete='CASCADE'), nullable=False)
command = Column(Integer, nullable=False)
started_at = Column(BigInteger, nullable=False)
ends_at = Column(BigInteger, nullable=False)
type = Column(Integer, default=None)
Entity can have one or none command. How to fetch pairs entity, command (entity can exists without command)
I tried like but it doesn't work
for e, c in session.query(EntityModel, CommandModel).join(CommandModel).filter(EntityModel.town_id == 100).all():
You can use outerjoin for a left outer join, which seems to be what you want.
http://docs.sqlalchemy.org/en/rel_0_7/orm/query.html#sqlalchemy.orm.query.Query.outerjoin