I'm trying to achieve polymorphism as described in SQLAlchemy docs.
I don't really mind single table or joined table inheritance.
My constraints are
Child classes have references to direct parent classes, and only direct parent classes, not any class in the hierarchy: child -> parent, grand-child -> child. (This kind of breaks polymorphism when you think of it, if polymorphism means that any child class can be substituted to classes above in the hierarchy.)
Unique constraint on name (common attribute) + parent ID (defined in each subclass).
Joined table
This would allow me to define the relation from child to parent, but I don't know how to represent the unique constraint on ("name", "parent_id") in Child.
class Parent(Base):
__tablename__ = "parents"
__mapper_args__ = {
"polymorphic_on": "type_",
"polymorphic_identity": "parent",
}
id = sqla.Column(sqla.Integer, primary_key=True)
name = sqla.Column(sqla.String(80), nullable=False)
type_ = sqla.Column(sqla.String(50))
class Child(Parent):
__tablename__ = "children"
__mapper_args__ = {
"polymorphic_identity": "child",
}
id = sqla.Column(sqla.ForeignKey("parents.id"), primary_key=True)
parent_id = sqla.Column(sqla.ForeignKey("parents.id"), nullable=False)
From this question, I must use a single table to enforce the constraint at DB level.
Single table
Here, I can define the unique constraint. But I don't know how to restrict the relation to parent class to a specific type. E.g. ensure parent_id is a relation pointing to family table but only to rows of type parent.
class Parent(Base):
__tablename__ = "family"
__mapper_args__ = {
"polymorphic_on": type_,
"polymorphic_identity": "parent",
}
id = sqla.Column(sqla.Integer, primary_key=True)
name = sqla.Column(sqla.String(80), nullable=False)
class Child(Parent):
__table_args__ = (sqla.UniqueConstraint("parent_id", "name"),)
__mapper_args__ = {
"polymorphic_identity": "child",
}
parent_id = sqla.Column(sqla.ForeignKey("family.id"), nullable=False)
class GrandChild(Child):
__table_args__ = (sqla.UniqueConstraint("child_id", "name"),)
__mapper_args__ = {
"polymorphic_identity": "grandchild",
}
child_id = sqla.Column(sqla.ForeignKey("family.id"), nullable=False)
How could I have both the relation and the unique constraint?