SQLAlchemy - Mapping self-referential relationship as one to many (declarative form)

PythonSqlalchemy

Python Problem Overview


I want to map a Tag entity using declarative method with SQLAlchemy. A tag can have a parent (another Tag).

I have:

class Tag(Base):
    __tablename__ = 'tag'
    
    id = Column(Integer, primary_key=True)
    label = Column(String)
    
    def __init__(self, label, parentTag=None):
        self.label = label

How can I add the "parent" relationship?

Python Solutions


Solution 1 - Python

You add a ForeignKey referencing the parent, and then create a relationship that specifies the direction via remote_side. This is documented under adjacency list relationships. For declarative you'd do something like this:

class Tag(Base):
    __tablename__ = 'tag'

    id = Column(Integer, primary_key=True)
    label = Column(String)
    parent_id = Column(Integer, ForeignKey('tag.id'))
    
    parent = relationship('Tag', remote_side=[id])

If you want the reverse relation also, add backref='children' to the relationship definition.

Solution 2 - Python

If you need children, you need to use uselist:

class Tag(Base):
    __tablename__ = 'tag'

    id = Column(Integer, primary_key=True)
    label = Column(String)
    child_id = Column(Integer, ForeignKey('tag.id'))

    children = relation('Tag', remote_side=[id], uselist=True)

Solution 3 - Python

class Company(BaseModel):
    __tablename__ = 'companies'
    companyName = db.Column(db.String(50))
    contactPerson = db.Column(db.String(50))
    email = db.Column(db.String(50))
    mobile = db.Column(db.String(20))
    parentID = db.Column(db.Integer, db.ForeignKey('companies.id'))  # parent company ID
    childrenCompany = db.relationship('Company', remote_side='Company.id',
                                    backref=db.backref('children_company'))  # parent Company

use:

In [2]: company_query = Company.query.get_or_404(1)

In [3]: company_query.children_company
Out[3]: 
[<app.models.user.Company at 0x10f527850>,
 <app.models.user.Company at 0x10f527c10>]

Solution 4 - Python

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHugoView Question on Stackoverflow
Solution 1 - PythonAnts AasmaView Answer on Stackoverflow
Solution 2 - PythonFarshid AshouriView Answer on Stackoverflow
Solution 3 - PythonEds_kView Answer on Stackoverflow
Solution 4 - PythonCat Plus PlusView Answer on Stackoverflow