Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comment écrire une migration pour changer la clé primaire du modèle avec ManyToManyField

Je me suis donc retrouvé avec SQL pour le réparer. Le cœur de ma solution est ci-dessous - essentiellement je

  • créer un index sur user_id dans le nouveau profil
    • cet index doit exister avant que je puisse le référencer en tant que clé étrangère
  • créer une nouvelle table de passage
    • J'ai commencé avec la sortie de SHOW CREATE TABLE userprofile_userprofile_subjects (spécifique à MySQL)
    • J'ai légèrement modifié les noms de clé et les noms de contrainte
  • copier toutes les données dans la nouvelle table de passage
  • déposez l'ancien tableau traversant
  • renommer la nouvelle table de passage pour avoir le nom de l'ancienne table de passage
  • faites enfin les opérations que les migrations django ont générées automatiquement pour moi

J'espère que ça aidera quelqu'un d'autre. Et je serais toujours intéressé de connaître une meilleure 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,
        ),
    ]