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

相關文章
相關標籤/搜索