django - 如何使用 Django 中的迁移和数据向现有 ManyToManyField 添加直通选项

标签 django django-models django-migrations

我在文档或在线找不到特定问题的引用。

我有一个多对多的关系。

class Books(models.Model):
    name = models.CharField(max_length=100)

class Authors(models.Model):
    name = models.CharField(max_length=100)
    books = models.ManyToManyField(Books)

这有迁移和数据。现在我需要使用 through 选项来在包含多对多关系的表中添加一个额外的字段。
class Authorship(models.Model):
    book = models.ForeignKey(Books)
    author = models.ForeignKey(Authors)
    ordering = models.PositiveIntegerField(default=1)

class Authors(models.Model):
    name = models.CharField(max_length=100)
    books = models.ManyToManyField(Books, through=Authorship)

当我运行迁移时,django 会为 Authorship 创建新的迁移模型。我尝试通过添加 ordering 手动创建迁移文件栏目Authorship表和修改 books栏目Authors表,但我遇到了一些迁移问题。
operations = [
    migrations.AddField(
        model_name='authorship',
        name='ordering',
        field=models.PositiveIntegerField(default=1),
    ),
    migrations.AlterField(
        model_name='authors',
        name='books',
        field=models.ManyToManyField(to='app_name.Books', through='app_name.Authorship'),
    ),
]

尝试迁移时,它给出 KeyError: ('app_name', u'authorship')我敢打赌还有其他事情会受到影响,从而导致错误。

我错过了什么?有没有其他方法可以解决这个问题?

最佳答案

有一种方法可以在没有数据迁移的情况下添加“通过”。
我根据 this @MatthewWilkes' answer 设法做到了.

因此,要将其转换为您的数据模型:

  • 创建 Authorship仅带 book 的型号和 author领域。指定表名以使用与您已有的自动生成的 M2M 表相同的名称。添加“通过”参数。
    class Authorship(models.Model):
        book = models.ForeignKey(Books)
        author = models.ForeignKey(Authors)
    
        class Meta:
            db_table = 'app_name_authors_books'
    
    class Authors(models.Model):
        name = models.CharField(max_length=100)
        books = models.ManyToManyField(Books, through=Authorship)
    
  • 生成迁移,但不要运行它。
  • 编辑生成的迁移并将迁移操作包装成 migrations. SeparateDatabaseAndState操作中的所有操作 state_operations字段(database_operations 留空)。你最终会得到这样的结果:
    operations = [
        migrations.SeparateDatabaseAndState(state_operations=[
            migrations.CreateModel(
                name='Authorship',
                fields=[
                    ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                    ('book', models.ForeignKey(to='app_name.Books')),
                ],
                options={
                    'db_table': 'app_name_authors_books',
                },
            ),
            migrations.AlterField(
                model_name='authors',
                name='books',
                field=models.ManyToManyField(through='app_name.Authorship', to='app_name.Books'),
            ),
            migrations.AddField(
                model_name='authorship',
                name='author',
                field=models.ForeignKey( to='app_name.Author'),
            ),
        ])
    ]
    
  • 您现在可以运行迁移并添加额外的 ordering字段到您的 M2M 表。

  • 编辑:
    显然,自动 M2M 表和模型定义的表在 DB 中生成的列名略有不同。 (我正在使用 Django 1.9.3。)

    在上述过程之后,我还必须手动更改具有 2 个字名称 ( two_words=models.ForeignKey(...) ) 的字段的列名 twowords_idtwo_words_id .

    关于django - 如何使用 Django 中的迁移和数据向现有 ManyToManyField 添加直通选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33257530/

    相关文章:

    python - 如何在 Python 3 上安装 Django?

    javascript - 在页面加载时将服务器端 HTML 转换为 Javascript MVC 的最佳方法是什么?

    python - migrations.RunPython 可以运行任意 python 代码吗?

    django 1.8 测试模型和迁移

    Django 管理员 : Can I add a filter for a model method?

    django - 为什么 Django on_delete 规则不起作用?

    django - Django 以复数和单数形式翻译一个单词的奇怪行为

    django - Django模型继承层次结构中字段的基于类的默认值

    python - Django Rest 模型配置不当 :

    django - 在 Django 中,当我调用 User.objects.create_user(用户名、电子邮件、密码) 时 - 为什么 post_save 被调用两次?