Created On: June 02, 2021, Last Updated On: June 05, 2021

SqlAlchemy ForeignKey relationship

Public

SqlAlchemy ForeignKey relationship

By Ozzie Ghani3 new


SQLAlchemy Relationship 

Suppose you have a fact table with multiple foreign keys and name mapping of these keys comes from a dimension table.  For the sake of the argument, I make it a simple example of a shipping table; something like following

Fact Table example

IDProductproduct_public_idShip_From_CountryShip_To_Country
shipped
1TVbcef6d9e-759b-4a1d-9491-d613123bd3f4
121
2Laptop2f33a131-7f65-4233-8495-8536e87a4967
231
3Monkeyf0fcad63-ba2d-42e9-9199-8988a1acc1c6
210


Now Dimension Table may look like following 

IDCountry
1USA
2Scotland
3Pakistan


Following is an example of classes defined for above structure 

Dimension table

class COUNTRIES(UserMixin, ResourceMixin, db.Model):

    __tablename__ = 'countries'

    id = db.Column(db.Integer, primary_key=True)
    country = db.Column(db.String(12), index=True)

    def __init__(self, **kwargs):
        # Call Flask-SQLAlchemy's constructor.
        super(COUNTRIES, self).__init__(**kwargs)

    @classmethod
    def find_country_by_id(cls, country_id):
        return COUNTRIES.query.filter(COUNTRIES.id == country_id).first()


Fact Table

class SHIPPING(UserMixin, ResourceMixin, db.Model):

    __tablename__ = 'shipping'

    id = db.Column(db.Integer, primary_key=True)
    product = db.Column('product', db.String(12), index=True)
    product_public_id = db.Column(UUID(as_uuid=True), default=uuid.uuid4, unique=True)
    
    ship_from_country_id = db.Column(db.Integer, db.ForeignKey(COUNTRIES.id))
    ship_to_country_id = db.Column(db.Integer, db.ForeignKey(COUNTRIES.id))
    ship_from_country = db.relationship('COUNTRIES', foreign_keys=[ship_from_country_id])
    ship_to_country = db.relationship('COUNTRIES', foreign_keys=[ship_to_country_id])
    
    shipped = db.Column(db.Boolean(), nullable=False, server_default='0')
    
    def __init__(self, **kwargs):
        # Call Flask-SQLAlchemy's constructor.
        super(SHIPPING, self).__init__(**kwargs)


Above example will add logical columns ship_from_country, ship_to_country ] for us to collect the values from. But if you query the database, or run a describe statement on the table, you will not see the columns. 


How to Query 


r = SHIPPING.query.get(1)

print("\n\n\n\n\n===============")
print(r)
print('Product Name', r.product)
print('Product Public ID', r.product_public_id)
print('Ship From Country ID', r.ship_from_country_id)
print('Ship To Country ID', r.ship_to_country_id)
print('Ship From Country', r.ship_from_country.country) # column value comes from Dim Table
print('Ship From Country', r.ship_to_country.country) # column value comes from Dim Table
print('Shipped Yet?', r.shipped)  # return True or False
print("\n\n\n\n\n===============")