How to write migration to change primary key of model with ManyToManyField

前端 未结 1 489
野性不改
野性不改 2021-01-19 19:23

I have a UserProfile model that refers to my User model with a OneToOneField. I also use the post_save signal to auto cr

相关标签:
1条回答
  • 2021-01-19 19:41

    So I ended up with SQL to fix it. The core of my solution is below - basically I

    • create an index on user_id in the new profile
      • this index needs to exist before I can reference it as a foreign key
    • create a new through table
      • I started with the output of SHOW CREATE TABLE userprofile_userprofile_subjects (MySQL specific)
      • I modified the key names and constraint names slightly
    • copy all the data into the new through table
    • drop the old through table
    • rename the new through table to have the name of the old through table
    • finally do the operations that django migrations automatically generated for me

    I hope this helps someone else. And I'd still be interested to know about a better solution.

    from django.db import migrations
    
    class Migration(migrations.Migration):
    
        dependencies = [
            # ...
        ]
    
        operations = [
            migrations.RunSQL(
                'ALTER TABLE userprofile_userprofile '
                'ADD INDEX `userprofile_userprofile_1234abcd` (user_id)'
            ),
            migrations.RunSQL (
                'CREATE TABLE userprofile_temp_table ('
                '`id` int(11) NOT NULL AUTO_INCREMENT, '
                '`userprofile_id` int(11) NOT NULL, '
                '`subject_id` int(11) NOT NULL, '
                'PRIMARY KEY (`id`), '
                'UNIQUE KEY `userprofile_userprofile_subjects_userprofile_us_7ded3060_uniq` (`userprofile_id`,`subject_id`), '
                'KEY `userprofile_userprofile_subject_1be9924f` (`userprofile_id`), '
                'KEY `userprofile_userprofile_subject_e5a9504a` (`subject_id`), '
                'CONSTRAINT `subject_id_refs_id_69796996` FOREIGN KEY (`subject_id`) REFERENCES `otherapp_subject` (`id`), '
                'CONSTRAINT `userprofile_user_id_refs_user_id_1234abcd` FOREIGN KEY (`userprofile_id`) REFERENCES `userprofile_userprofile` (`user_id`) '
                ') ENGINE=InnoDB AUTO_INCREMENT=35500 DEFAULT CHARSET=utf8 '
            ),
            migrations.RunSQL (
                'INSERT INTO userprofile_temp_table '
                '(userprofile_id, subject_id) '
                '('
                '  SELECT userprofile_userprofile.user_id, userprofile_userprofile_subjects.subject_id'
                '    FROM userprofile_userprofile_subjects'
                '    INNER JOIN userprofile_userprofile'
                '    ON userprofile_userprofile_subjects.userprofile_id ='
                '        userprofile_userprofile.id'
                ')'
            ),
            migrations.RunSQL (
                'DROP TABLE `userprofile_userprofile_subjects`'
            ),
            migrations.RunSQL (
                'RENAME TABLE `userprofile_temp_table` TO `userprofile_userprofile_subjects`'
            ),
            migrations.RemoveField(
                model_name='userprofile',
                name='id',
            ),
            migrations.AlterField(
                model_name='userprofile',
                name='user',
                field=models.OneToOneField(
                    primary_key=True, serialize=False, to=settings.AUTH_USER_MODEL
                ),
                preserve_default=True,
            ),
        ]
    
    0 讨论(0)
提交回复
热议问题