上文讲了自引用数据模型的一对多场景,主要用于构建树形数据结构。自引用数据模型还有多对多的场景,比如文章引用,参考等等,这个时候需要引入一张中间表来完成。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| from typing import List, Optional
from sqlmodel import Field, Relationship, Session, SQLModel, create_engine, select
class PaperSimilarLink(SQLModel, table=True): paper_id: Optional[int] = Field( default=None, foreign_key="paper.id", primary_key=True ) similar_id: Optional[int] = Field( default=None, foreign_key="paper.id", primary_key=True )
class Paper(SQLModel, table=True): id: Optional[int] = Field(default=None, primary_key=True) similar: List["Paper"] = Relationship( link_model=PaperSimilarLink, sa_relationship_kwargs={ "primaryjoin": "Paper.id == PaperSimilarLink.paper_id", "secondaryjoin": "Paper.id == PaperSimilarLink.similar_id", }, )
sqlite_file_name = "database.db" sqlite_uri = f"sqlite:///{sqlite_file_name}" engine = create_engine(sqlite_uri, echo=True) SQLModel.metadata.drop_all(engine) SQLModel.metadata.create_all(engine)
def test() -> None: with Session(engine) as session: SQLModel.metadata.create_all(engine)
p1 = Paper(id=1) p2 = Paper(id=2) p3 = Paper(id=3) session.add_all([p1, p2, p3]) session.commit()
session.refresh(p1) session.refresh(p2) session.refresh(p3)
p1.similar = [p2, p3] session.add(p1) session.commit()
p2.similar = [p1] session.add(p1) session.commit()
statement = select(Paper) paper = session.exec(statement).unique().all()
for i in paper: print(i.id, i.similar)
if __name__ == "__main__": test()
|
来源:https://github.com/fastapi/sqlmodel/issues/127