SQLAlchemy Join Query 获得的不一样数据行相同数据是同一个实例

在开发的时候遇到了一个很大的坑(仍是由于是我不了解 SQLAlchemy 吧😷), 记录一下省得日后再踩...python

事情是这样的, 有三张表, 快速地模拟一下表结构:bash

student表
|------+--------+----------+--------------|
|  id  +  name  +  gender  +  deleted_at  |
|------+--------+----------+--------------|

course表
|------+---------+--------------+--------------|
|  id  +  title  +  teacher_id  +  deleted_at  |
|------+---------+--------------+--------------|

student_course_rel表
|------+--------------+-------------+--------------|
|  id  |  student_id  +  course_id  +  deleted_at  |
|------+--------------+-------------+--------------|

复制代码

这里模拟了一个场景需求, 须要列出某位老师所教授的不一样课程的学生列表, 而且要支持全量更新(更新的时候传入的列表为所有学生列表(新增和删除)) 这个时候我要 Join 三张表, 而且同一个学生对应的不一样课程的 rel id 也得记录, 这样我就能够知道那些是新增的那些是删除的. 也就是说, 我须要将用户和课程的 rel id 进行绑定. 因此, 我就用这条语句进行 Query:session

teacher_id = 'teacher_id'
query_result = db.session.query(Course, Student, StudentCourseRel)\
    .join(StudentCourseRel, Course.id == StudentCourseRel.course_id)\
    .join(Student, StudentCourseRel.student_id == Student.id)\
    .filter(Course.teacher_id == teacher_id, Course.deleted_at.is_(None),
            Student.deleted_at.is_(None), StudentCourseRel.deleted_at.is_(None))\
    .all()
# query 出来的结果大体是这样的
[(course_a, stu_1, rel_1), (course_a, stu_2, rel_2), (course_b, stu_1, rel_3), (course_c, stu_3, rel_4)]
复制代码

这个时候, query 出来的结果确实是我想要的, 每一个用户每一个课程都会有一条记录. 列表没有任何问题. 可是在更新的时候就出 bug 了.
问题就出在student, course, rel_id绑定这一步用户. 和课程关系的绑定我是遍历数据列表, 而且将 rel id 做为 student 的一个属性.app

# 处理数据
result = set()
for item in query_result:
    course, student, rel = item
    if course not in result:
        course.students = []
        result.add(container)
    user.rel_id = rel.id
    course.users.append(user)
return result
复制代码

就上例而言, SQLAlchemy 获得的数据中, course_a 所对应的 stu_1 和 course_b 所对应的 stu_1 是同一个实例, 也就是说在遍历而且进行赋值 rel_id 的时候, 后项会直接覆盖前项, 因此会形成数据的混乱.spa

这里就暴露出来一个点, 也就是说 SQLAlchemy 在处理 Join 后获得的一样数据是采用 同一个实例 对不一样数据行进行拼接.code

相关文章
相关标签/搜索