Django使用ManyToManyField创建记录时出现bigint类型输入语法错误
错误成因
核心原因是多对多自动生成的中间表producers_producer_product_categories中,producer_id字段类型和当前Producer的主键类型不匹配:
- 你最初使用Django默认自增主键时,自动生成的中间表
producer_id字段为bigint类型 - 后续你将Producer的主键改为关联User表
userID的OneToOneField,实际主键类型变为CharField,但Django自动生成中间表时没有正确识别到主键类型变更,或者旧的表结构残留没有被完全清理,导致中间表的producer_id仍然是bigint类型,存入字符串类型的主键值John97时触发类型错误。
解决办法
推荐用自定义中间表的方案彻底解决类型歧义,操作步骤如下:
- 先定义显式的多对多中间模型,明确指定关联字段的映射关系
# 在Producers app的models.py中添加该中间模型 class ProducerCategory(models.Model): # 显式指定to_field映射到Producer的实际主键字段 producer = models.ForeignKey(Producer, on_delete=models.CASCADE, to_field="userID") # 显式指定to_field映射到Category的实际主键字段 category = models.ForeignKey("Products.Category", on_delete=models.CASCADE, to_field="categoryID") class Meta: # 可以使用新表名避免旧表残留问题,也可以沿用原来的表名 db_table = "producer_category_rel" # 保持多对多的唯一约束 constraints = [ models.UniqueConstraint(fields=["producer", "category"], name="unique_producer_category") ]
- 修改Producer的ManyToManyField字段,指定through参数关联自定义中间表
# 修改Producer中的product_categories字段 product_categories = models.ManyToManyField( 'Products.Category', related_name='producers', # 原related_name为category逻辑不符,建议修改为producers表示反向拿到关联的生产者列表 blank=True, through=ProducerCategory )
- 彻底清理旧结构重新生成迁移
- 清空数据库中所有和Producer、多对多中间表相关的旧表
- 删除各app下
migrations目录中除__init__.py之外的所有文件 - 执行
python manage.py makemigrations重新生成迁移文件 - 执行
python manage.py migrate应用迁移,此时生成的中间表producer字段类型会和User表的userID保持一致为varchar类型,即可解决类型报错问题。
如果不想自定义中间表,也可以生成迁移后手动修改迁移文件中中间表producer_id的字段类型为CharField(max_length=50),再执行迁移即可。
额外优化提示
你当前的calculateRating方法存在逻辑错误:代码中self.rating = self.rating + 1会直接给评分加1,正确逻辑应该是给评价数self.number_ratings += 1后再计算平均评分。
内容的提问来源于stack exchange,提问作者Alicklaz
相关产品推荐
相关产品推荐

