I have an application which is in BETA mode. The model of this app has some classes with an explicit primary_key. As a consequence Django use the fields and doesn\'t create
I managed to do this with django 1.10.4 migrations and mysql 5.5, but it wasn't easy.
I had a varchar primary key with several foreign keys. I added an id field, migrated data and foreign keys. This is how:
id = models.IntegerField(default=0) field to my main model and generated an auto migration.Simple data migration to generate new primary keys:
def fill_ids(apps, schema_editor):
Model = apps.get_model('', '')
for id, code in enumerate(Model.objects.all()):
code.id = id + 1
code.save()
class Migration(migrations.Migration):
dependencies = […]
operations = [migrations.RunPython(fill_ids)]
Migrating existing foreign keys. I wrote a combined migration:
def change_model_fks(apps, schema_editor):
Model = apps.get_model('', '') # Our model we want to change primary key for
FkModel = apps.get_model('', '') # Other model that references first one via foreign key
mapping = {}
for model in Model.objects.all():
mapping[model.old_pk_field] = model.id # map old primary keys to new
for fk_model in FkModel.objects.all():
if fk_model.model_id:
fk_model.model_id = mapping[fk_model.model_id] # change the reference
fk_model.save()
class Migration(migrations.Migration):
dependencies = […]
operations = [
# drop foreign key constraint
migrations.AlterField(
model_name='',
name='model',
field=models.ForeignKey('', blank=True, null=True, db_constraint=False)
),
# change references
migrations.RunPython(change_model_fks),
# change field from varchar to integer, drop index
migrations.AlterField(
model_name='',
name='model',
field=models.IntegerField('', blank=True, null=True)
),
]
Swapping primary keys and restoring foreign keys. Again, a custom migration. I auto-generated the base for this migration when I a) removed primary_key=True from the old primary key and b) removed id field
class Migration(migrations.Migration):
dependencies = […]
operations = [
# Drop old primary key
migrations.AlterField(
model_name='',
name='',
field=models.CharField(max_length=100),
),
# Create new primary key
migrations.RunSQL(
['ALTER TABLE CHANGE id id INT (11) NOT NULL PRIMARY KEY AUTO_INCREMENT'],
['ALTER TABLE CHANGE id id INT (11) NULL',
'ALTER TABLE DROP PRIMARY KEY'],
state_operations=[migrations.AlterField(
model_name='',
name='id',
field=models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
)]
),
# Recreate foreign key constraints
migrations.AlterField(
model_name='',
name='model',
field=models.ForeignKey(blank=True, null=True, to='.'),
]
- 热议问题