Sqlalchemy 不包含查询的多对多关系

Sqlalchemy 不包含查询的多对多关系,sqlalchemy,flask-sqlalchemy,Sqlalchemy,Flask Sqlalchemy,我在Sqlalchemy中定义了多对多关系。我尝试使用query-contains和not-contains。但是,使用“notcontains”进行查询并不能得到所需的结果,特别是在有多个条目的情况下。我需要帮助来完善我的查询,下面给出了示例代码:- from sqlalchemy import Column, Integer, String, ForeignKey, Table from sqlalchemy.ext.declarative import declarative_base f

我在Sqlalchemy中定义了多对多关系。我尝试使用query-contains和not-contains。但是,使用“notcontains”进行查询并不能得到所需的结果,特别是在有多个条目的情况下。我需要帮助来完善我的查询,下面给出了示例代码:-

from sqlalchemy import Column, Integer, String, ForeignKey, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

Base = declarative_base()

association_table = Table('association', Base.metadata,
    Column('student_id', Integer, ForeignKey('student_table.id')),
    Column('course_id', Integer, ForeignKey('course_table.id'))
)

class Student(Base):
    __tablename__ = 'student_table'

    id = Column(Integer, primary_key=True)
    student_name = Column(String)
    courses = relationship("Course",
                          secondary=association_table,
                          backref="students")

    def __repr__(self):
        return f'Student : {self.student_name}'

class Course(Base):
    __tablename__ = 'course_table'

    id = Column(Integer, primary_key=True)
    course_name = Column(String)

    def __repr__(self):
        return f'Course : {self.course_name}'


# Create the engine
engine = create_engine('sqlite:///:memory:', echo=False)
Session = sessionmaker(bind=engine)
session = Session()

# Create All Tables
Student.metadata.create_all(engine)
Course.metadata.create_all(engine)

# Create new entries for Student and Course
student1 = Student(student_name="John")
student2 = Student(student_name="Steve")
course1 = Course(course_name="CS101")
course2 = Course(course_name="DS101")

# Associate Student and Course
student1.courses.append(course1)
student1.courses.append(course2)
student2.courses.append(course1)

# Commit the changes
session.add(student1)
session.add(student2)
session.add(course1)
session.add(course2)
session.commit()

# Query the database and print

print("Students having course - DS101")
print(session.query(Student).filter(Student.courses.any(Course.course_name.contains("DS101"))).all())
print("Students not having course - DS101")
print(session.query(Student).filter(Student.courses.any(~Course.course_name.contains("DS101"))).all())
print("Students having course - CS101")
print(session.query(Student).filter(Student.courses.any(Course.course_name.contains("CS101"))).all())
print("Students not having course - CS101")
print(session.query(Student).filter(Student.courses.any(~Course.course_name.contains("CS101"))).all())
我在运行代码段时得到了以下结果,使用not contains似乎不是期望的结果

Students having course - DS101
[Student : John]
Students not having course - DS101
[Student : John, Student : Steve]
Students having course - CS101
[Student : John, Student : Steve]
Students not having course - CS101
[Student : John]
>>> session.query(Student).filter(Student.courses.any(Course.course_name.contains("DS101"))).filter(association_table.c.course_id == Course.id).all()
[Student : John]
>>> session.query(Student).filter(Student.courses.any(~Course.course_name.contains("DS101"))).filter(association_table.c.course_id == Course.id).all()
[Student : John, Student : Steve]
>>> 
基于“关联_表”,我确实了解这里发生了什么,即当我使用not contains时,我会得到与第二个课程相关联的记录结果

>>> session.query(association_table).all()
[(1, 1), (2, 1), (1, 2)]
>>> session.query(association_table).join(Course).filter(Course.course_name.contains("CS101")).all()
[(1, 1), (2, 1)]
>>> session.query(association_table).join(Course).filter(~Course.course_name.contains("CS101")).all()
[(1, 2)]
>>> 
我试图改进这个查询,但没有成功。当使用“not contains”时,能否有人指导/帮助获得所需的结果

编辑(使用
any
,希望与
join
一起使用)

我能够使它与
任何
一起工作。是否可以使其与
join
一起工作

使用否定外部
any
使其工作

session.query(Student).filter(~Student.courses.any(Course.course_name.contains("CS101"))).all()
不起作用

session.query(Student).join(association_table).join(Course).filter(~Course.course_name.contains("CS101")).all()