I had to change the primary key of a django model, and I wanted to create a migration for this.
The previous model was using django automatic primary key fields
I firstly changed the model to include the new uuid
field, and added the id
field (the old primary key), like this:
uuid = models.UUIDField(
unique=True, primary_key=True, default=uuid.uuid4, editable=False
)
id = models.IntegerField(null=True, blank=True)
Then I create the migration, they:
- Create a new
uuid
field/column in the database - Iterate over the existing items in the table, to generate an uuid for them
- Update the eventual references to the model so that it continues to work
- Change the old primary key to a different type
- Drop the old index
- Mark the new primary key as such
To generate the migrations I did django-admin makemigrations
, and iterated on
it. Here is the migration I ended up with:
import uuid
from django.db import migrations, models
# This is done in pure python, but can probably be faster with SQL queries directly
# for a large database.
def gen_uuid(apps, schema_editor):
DataLayer = apps.get_model("umap", "DataLayer")
for row in DataLayer.objects.all():
row.uuid = uuid.uuid4()
row.save(update_fields=["uuid"])
class Migration(migrations.Migration):
dependencies = [
("umap", "0017_migrate_to_openstreetmap_oauth2"),
]
operations = [
migrations.AddField(
model_name="datalayer",
name="uuid",
field=models.UUIDField(default=uuid.uuid4, editable=False, null=True),
),
migrations.RunPython(gen_uuid, reverse_code=migrations.RunPython.noop),
migrations.RunSQL(
"ALTER TABLE umap_datalayer DROP CONSTRAINT umap_datalayer_pkey"
),
migrations.AlterField(
"datalayer", name="id", field=models.IntegerField(null=True, blank=True)
),
migrations.AlterField(
model_name="datalayer",
name="uuid",
field=models.UUIDField(
default=uuid.uuid4, editable=False, unique=True, primary_key=True
),
),
]
#django , #orm , #migrations - Posté dans la catégorie code