至少,如果程序数量相对较少,您可以将and_ 的要求放在您的.filter 中:
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
engine = sa.create_engine("sqlite:///:memory:", echo=True)
Base = declarative_base()
# association table
place_procedure = sa.Table(
"place_procedure",
Base.metadata,
sa.Column("place_id", sa.ForeignKey("place.id"), primary_key=True),
sa.Column("procedure_id", sa.ForeignKey("procedure.id"), primary_key=True),
)
class Place(Base):
__tablename__ = "place"
id = sa.Column("id", sa.Integer, primary_key=True, autoincrement=False)
procedures = sa.orm.relationship(
"Procedure", secondary=place_procedure, back_populates="places"
)
def __init__(self, id, procedures):
self.id = id
self.procedures = procedures
def __repr__(self):
return f"<Place(id={self.id})>"
class Procedure(Base):
__tablename__ = "procedure"
id = sa.Column("id", sa.String(50), primary_key=True)
places = sa.orm.relationship(
"Place", secondary=place_procedure, back_populates="procedures"
)
def __init__(self, id):
self.id = id
def __repr__(self):
return f"<Procedure(id='{self.id}')>"
Base.metadata.create_all(engine)
Session = sa.orm.sessionmaker(bind=engine)
session = Session()
# test data
proc1 = Procedure("procedure1")
proc2 = Procedure("procedure2")
proc4 = Procedure("procedure4")
place0 = Place(0, [])
place1 = Place(1, [proc1])
place2 = Place(2, [proc2])
place3 = Place(3, [proc2, proc1])
place4 = Place(4, [proc4])
place5 = Place(5, [proc4, proc1])
place6 = Place(6, [proc4, proc2])
place7 = Place(7, [proc4, proc2, proc1])
session.add_all(
[
proc1,
proc2,
proc4,
place1,
place2,
place3,
place4,
place5,
place6,
place7,
]
)
session.commit
# test code
places_with_procedure1_and_procedure2 = (
session.query(Place)
.filter(
sa.and_(
Place.procedures.contains(proc1), Place.procedures.contains(proc2)
)
)
.all()
)
print(places_with_procedure1_and_procedure2)
"""console output:
[<Place(id=3)>, <Place(id=7)>]
"""