Django ManyToManyField设置关联属性及through参数报错解决
Django多对多关联下多图书阅读进度实现方案
报错原因
你遇到的fields.E336错误核心原因是:Django自定义多对多中间表必须同时包含关联两个模型的外键字段,你编写的ReadingBook中间表仅添加了指向Book的外键,缺失指向User的外键,框架无法识别该表作为User和Book的关联中间表,因此抛出异常。
修正后的完整模型代码
from django.db import models class Book(models.Model): name = models.CharField(max_length=128) def __str__(self): return self.name class User(models.Model): name = models.CharField(max_length=64) current_reading_books = models.ManyToManyField('Book', through='ReadingBook') def __str__(self): return self.name class ReadingBook(models.Model): # 补全指向User的外键,和指向Book的外键共同组成多对多关联 user = models.ForeignKey('User', on_delete=models.CASCADE) book = models.ForeignKey('Book', on_delete=models.CASCADE) # 存储该用户对应该本书的阅读进度 current_reading_page = models.IntegerField(default=0) class Meta: # 添加联合唯一约束,避免同一用户重复添加同一本书的阅读记录 unique_together = ('user', 'book')
常用操作示例
- 新增阅读进度
# 创建测试数据 user_a = User.objects.create(name="用户A") book1 = Book.objects.create(name="book1") book2 = Book.objects.create(name="book2") book3 = Book.objects.create(name="book3") # 直接操作中间表写入用户对应书籍的阅读页码 ReadingBook.objects.create(user=user_a, book=book1, current_reading_page=100) ReadingBook.objects.create(user=user_a, book=book2, current_reading_page=10) ReadingBook.objects.create(user=user_a, book=book3, current_reading_page=0)
- 查询用户所有在读图书及进度
# 取出用户A的所有阅读记录 all_reading_progress = user_a.readingbook_set.all() for progress in all_reading_progress: print(f"书籍名:{progress.book.name},当前阅读页码:{progress.current_reading_page}")
- 更新指定书籍的阅读进度
# 将用户A读book1的进度更新为120页 ReadingBook.objects.filter(user=user_a, book=book1).update(current_reading_page=120)
注意:使用自定义
through参数指定中间表的多对多字段,不再支持Django默认提供的add()、set()、remove()快捷关联操作,所有关联关系的增删改都需要直接操作中间表完成。
内容的提问来源于stack exchange,提问作者Tser Wattney
相关产品推荐
相关产品推荐

