How to set relationship between two tables in SQLAlchemy? - python

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'))

Related

Flask SQLAlchemy Association Table: error creating backref

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

sqlalchemt---SAWarning: fully NULL primary key identity cannot load any object

model:
'''任务工单'''
__tablename__ = 'task'
id = db.Column(db.Integer, primary_key=True, nullable=False, autoincrement=True)
user_id = db.Column(db.Integer, index=True, nullable=False)
dep_id = db.Column(db.Integer, index=True, nullable=False)
title = db.Column(db.String(200), nullable=False, index=True)
content = db.Column(db.Text, nullable=False)
cate = db.Column(db.SmallInteger, default=1,`enter code here`)
add_time = db.Column(db.Integer, default=int(time.time()), comment="添加时间")
is_top = db.Column(db.SmallInteger, default=0, comment="是否加急 1--加急 0--不加急")
desgin_id = db.Column(db.Integer,comment="设计人员的id")
update_time = db.Column(db.Integer, comment="修改时间")
review_time = db.Column(db.Integer, comment="审核时间")
assignment_time = db.Column(db.Integer, comment='分配时间')
fiannce_time = db.Column(db.Integer, comment='完成时间')
invalid_time = db.Column(db.Integer, comment='无效时间')
desgin_time = db.Column(db.Integer, comment="开始设计时间")
state = db.Column(db.SmallInteger, default=1, comment="状态:1--初始化待分配 2--带设计 3--设计中 4--提交待审核(审核中) 5--驳回 7--完成 0--无效")
use:
taskDicts = Task.query.filter_by(state=state).order_by(desc(Task.is_top),asc(Task.add_time)).offset(offset).limit(10).all()
venv/lib/python3.7/site-packages/sqlalchemy/orm/loading.py:246:
SAWarning: fully NULL primary key identity cannot load any object.
This condition may raise an error in a future release.

SqlAlchemy Error on Creating multiple foreign key to one table

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.

how to insert symbol(,) to result in SQLAlchemy level?

#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.

How to fetch pairs from join where second value can be none, left join

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

Categories