You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级至Django 1.11时出现多对多关系列不存在问题求助

解决Django 1.11升级后自定义多对多Through表失效的问题

嘿,我太懂这种升级后突然掉坑的感觉了!Django 1.11在多对多关系的through表处理上,确实强化了不少一致性校验,尤其是你这种“借用”自动生成的中间表来扩展字段的操作,很容易触发之前没遇到的问题。下面给你一步步拆解解决方案:

1. 精准匹配原有中间表结构,重建自定义Through模型

你之前“借用”的api_session_pollgroups是Django自动生成的多对多中间表,它默认包含两个外键字段(对应Session和PollGroup模型),还有唯一联合约束。Django 1.11会严格校验自定义through模型和实际表结构的一致性,所以必须精准复刻这些内容,再加上你的order字段:

from django.db import models
from .models import Session, PollGroup

class SessionPollGroup(models.Model):
    # 必须和原有表的外键字段名完全一致,用db_column确保映射正确
    session = models.ForeignKey(Session, on_delete=models.CASCADE, db_column='session_id')
    pollgroup = models.ForeignKey(PollGroup, on_delete=models.CASCADE, db_column='pollgroup_id')
    # 你的自定义排序字段
    order = models.IntegerField(default=0)

    class Meta:
        # 明确指定使用已存在的表,不能写错表名
        db_table = 'api_session_pollgroups'
        # 原有自动生成表自带的唯一约束,必须加上,否则Django 1.11会报错
        unique_together = ('session', 'pollgroup')
        # 可选:如果需要默认按order排序,可以加上这行
        ordering = ['order']

2. 修正Session模型的多对多关系定义

确保你的Session模型里的多对多字段,正确指向这个自定义的through模型,参数要和之前保持一致(比如related_name):

class Session(models.Model):
    # 其他模型字段...
    poll_groups = models.ManyToManyField(
        PollGroup,
        through='SessionPollGroup',
        related_name='sessions'  # 如果之前有这个参数,一定要保留
    )

3. 处理迁移:避免重复创建表,只添加order字段

因为你是在已有表上扩展字段,不能让Django自动生成创建表的迁移。你需要手动生成空迁移,然后添加字段操作:

  • 首先生成一个空迁移文件:
    python manage.py makemigrations --empty your_app_name
    
  • 打开生成的迁移文件,修改成只添加order字段的操作:
    from django.db import migrations, models
    
    class Migration(migrations.Migration):
        # 替换成你上一个迁移的名称
        dependencies = [
            ('your_app_name', '00XX_previous_migration'),
        ]
    
        operations = [
            migrations.AddField(
                model_name='sessionpollgroup',
                name='order',
                field=models.IntegerField(default=0),
            ),
        ]
    
  • 最后执行迁移:
    python manage.py migrate
    

4. 调整单元测试中的多对多操作逻辑

Django 1.11对自定义through表的add()/remove()方法限制更严格——默认的add()不会处理自定义字段(比如你的order),所以如果测试里有直接调用session.poll_groups.add(pollgroup)的代码,需要改成显式创建中间表实例:

原来的代码:

session.poll_groups.add(pollgroup)

改成:

SessionPollGroup.objects.create(session=session, pollgroup=pollgroup, order=1)

如果需要批量添加,记得给每个实例指定对应的order值。

额外注意点

  • 可以用python manage.py inspectdb api_session_pollgroups命令,生成原有表的模型代码,对比你的自定义模型,确保字段、约束完全一致,别漏了任何细节。
  • 如果你之前给中间表加过索引,也要在自定义模型的Meta里用indexes声明出来,Django 1.11会校验索引的存在。

内容的提问来源于stack exchange,提问作者bharling

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 09:11:14