您可以指定primaryjoin每个属性relationship以区分两者:
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship, sessionmaker
connection_uri = (
"mssql+pyodbc://@localhost:49242/myDb?driver=ODBC+Driver+17+for+SQL+Server"
)
engine = sa.create_engine(connection_uri)
with engine.begin() as conn:
conn.execute(sa.text("DROP TABLE IF EXISTS task_t"))
conn.execute(sa.text("DROP TABLE IF EXISTS user_t"))
Base = declarative_base()
class Task(Base):
__tablename__ = "task_t"
id = sa.Column(sa.Integer, primary_key=True)
description = sa.Column(sa.String(50))
author = sa.Column(sa.Integer, sa.ForeignKey("user_t.id"))
assignee = sa.Column(sa.Integer, sa.ForeignKey("user_t.id"))
def __repr__(self):
return f"<Task(id={self.id}, description='{self.description}')>"
class User(Base):
__tablename__ = "user_t"
id = sa.Column(sa.Integer, primary_key=True)
name = sa.Column(sa.String(50))
created_tasks = relationship(
Task,
primaryjoin="User.id == Task.author",
backref="user_created_tasks",
)
assigned_tasks = relationship(
Task,
primaryjoin="User.id == Task.assignee",
backref="user_assigned_tasks",
)
def __repr__(self):
return f"<User(id={self.id}, name='{self.name}')>"
Base.metadata.create_all(engine)
Session = sessionmaker(bind=engine)
session = Session()
homer = User(name="Homer")
bart = User(name="Bart")
lisa = User(name="Lisa")
session.add_all([homer, bart, lisa])
session.commit()
mow_the_lawn = Task(
description="Mow the lawn", author=homer.id, assignee=bart.id
)
wash_the_car = Task(
description="Wash the car", author=homer.id, assignee=lisa.id
)
session.add_all([mow_the_lawn, wash_the_car])
session.commit()
with engine.begin() as conn:
result = conn.execute(
sa.text("SELECT * FROM user_t ORDER BY id")
).fetchall()
print(result)
# [(1, 'Homer'), (2, 'Bart'), (3, 'Lisa')]
result = conn.execute(
sa.text("SELECT * FROM task_t ORDER BY id")
).fetchall()
print(result)
# [(1, 'Mow the lawn', 1, 2), (2, 'Wash the car', 1, 3)]
print(homer.created_tasks)
# [ <Task(id=1, description='Mow the lawn')>, <Task(id=2, description='Wash the car')>]
print(bart.assigned_tasks)
# [ <Task(id=1, description='Mow the lawn')>]