Search code examples
pythonsqlalchemydatabase-migration

Does adding sqlalchemy.orm.relationship to a model changes internal DB schema?


Does adding sqlalchemy.orm.relationship to a model changes internal DB schema? Do I need to add a DB migration script if the only thing that has changed in the ORM mapping is the orm.relationship being added?

For example original mapping:

class Service(Base):
    __tablename__ = 'service'
    id = sql.Column(sql.String(64), primary_key=True)
    type = sql.Column(sql.String(255))
    extra = sql.Column(sql.Text())


class Endpoint(Base):
    __tablename__ = 'endpoint'
    id = sql.Column(sql.String(64), primary_key=True)
    legacy_endpoint_id = sql.Column(sql.String(64))
    interface = sql.Column(sql.String(8), primary_key=True)
    region = sql.Column('region', sql.String(255))
    service_id = sql.Column(sql.String(64),
                            sql.ForeignKey('service.id'),
                            nullable=False)
    url = sql.Column(sql.Text())
    extra = sql.Column(sql.Text())

Modified mapping:

@@ -3,6 +3,7 @@
     id = sql.Column(sql.String(64), primary_key=True)
     type = sql.Column(sql.String(255))
     extra = sql.Column(sql.Text())
+    endpoints = sql.orm.relationship("Endpoint")


 class Endpoint(Base):
@@ -16,4 +17,5 @@
                             nullable=False)
     url = sql.Column(sql.Text())
     extra = sql.Column(sql.Text())
+    service = sql.orm.relationship("Service")

With the change above, do I need to add DB migration script?


Solution

  • I am assuming it is a one to many relationship (service to endpoints)

    No, you don't need to add anything to the migration script unless it's a many to many relationship. In that case an association table may be required, but then it'd (association table) already be part of your model. http://docs.sqlalchemy.org/en/latest/orm/relationships.html#many-to-many

    Also specifying the relationship only in one of the models is enough, for the other direction you can use backref option:

    class Service(Base):
        __tablename__ = 'service'
        id = sql.Column(sql.String(64), primary_key=True)
        type = sql.Column(sql.String(255))
        extra = sql.Column(sql.Text())
        endpoints = sql.orm.relationship("Endpoint", backref="service")
    

    This is a two way relationship now. Now .service on endpoint object will give you the corresponding service object. And .endpoints on service object will give you an array of endpoint objects. In case it's a one to one then you may specify uselist=False in relationship, then you'd get back a scalar instead of a list