如何让涉及跨外键应用唯一索引的 Django 迁移向后移动?

chi*_*983 7 python mysql django unique-constraint django-migrations

今天,我的任务是修复一堆迁移,以便它们可以从头开始完全前进和后退,而不依赖于从生产中的数据库转储开始。我遇到了这个。

class Migration(migrations.Migration):

dependencies = [
    migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ('content', '0038_merge'),
]

operations = [
    migrations.CreateModel(
        name='UserRoles',
        fields=[
            ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
            ('role', models.CharField(max_length=100, choices=[(b'editor', b'Editor Role'), (b'read_only', b'Read Only'), (b'writer', b'Writer Role')])),
            ('site', models.ForeignKey(related_name='site', to='content.Site')),
            ('user', models.ForeignKey(related_name='user_site_roles', to=settings.AUTH_USER_MODEL)),
        ],
    ),
    migrations.AlterUniqueTogether(
        name='userroles',
        unique_together=set([('user', 'site')]),
    ),
]
Run Code Online (Sandbox Code Playgroud)

向前和向后,这是它生成的 SQL。

BEGIN;
CREATE TABLE `content_userroles` (`id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY, `role` varchar(100) NOT NULL, `site_id` integer NOT NULL, `user_id` integer NOT NULL);
ALTER TABLE `content_userroles` ADD CONSTRAINT `content_userroles_user_id_798e435c65731cb9_uniq` UNIQUE (`user_id`, `site_id`);
ALTER TABLE `content_userroles` ADD CONSTRAINT `content_userroles_site_id_3eb32f440311bcb0_fk_sites_id` FOREIGN KEY (`site_id`) REFERENCES `sites` (`id`);
ALTER TABLE `content_userroles` ADD CONSTRAINT `content_userroles_user_id_6a54f536e78383a8_fk_auth_user_id` FOREIGN KEY (`user_id`) REFERENCES `auth_user` (`id`);

COMMIT;

BEGIN;
ALTER TABLE `content_userroles` DROP INDEX `content_userroles_user_id_798e435c65731cb9_uniq`;
DROP TABLE `content_userroles` CASCADE;

COMMIT;
Run Code Online (Sandbox Code Playgroud)

当它尝试删除唯一索引时,会遇到错误:

Cannot drop index 'content_userroles_user_id_798e435c65731cb9_uniq': needed in a foreign key constraint
Run Code Online (Sandbox Code Playgroud)

这是 Django 错误吗?是否有一种解决方法可以让看似简单的迁移变得可逆?有人建议我无论如何都应该压缩迁移堆栈,但我并不完全相信它会起作用,因为我不确定是否可以生成不会遇到此排序问题的这些命令的任何优化版本。我愿意接受任何级别的建议,无论它们看起来多么老套,因为我至少希望能从他们那里学到一些东西。我对 Django 相当缺乏经验,但在搜索了一整个下午后还没有找到类似的东西。我尝试将唯一索引创建放在后续迁移步骤中,因此先创建外键,然后创建唯一索引。但这并没有改变任何东西,因为一旦将唯一性应用于外键字段,就无法在不删除整个表的情况下将其删除。