django-pk-to-uuid
django-pk-to-uuid copied to clipboard
Writing custom Django migrations to convert data type of Primary Key, also updating Foreign Keys.
Django PK to UUID
Django migrations to convert integer primary key to UUID, also updating Foreign Keys. This has been tested on PostgreSQL database.
We have created two initial models in our Django app named app
as follows:
class Office(models.Model):
office_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=30)
description = models.TextField()
class Employee(models.Model):
employee_id = models.AutoField(primary_key=True)
office = models.ForeignKey(Office, on_delete=models.CASCADE)
name = models.CharField(max_length=30)
description = models.TextField()
The model Employee has a foreign key office
(stored as office_id
in the db). The field office_id
in Office
is currently of type Integer. We wish to now convert this to UUID. We make the following changes to the Office
model:
class Office(models.Model):
office_id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=30)
description = models.TextField()
The model Employee
stays the same. When Django autogenerated migrations are run, they throw an error, as it only tries to cast the int
values to UUID
. Making this change requires us to write our own migrations. You will find this in the django_pk_to_uuid.py
file in the repository. Here, I'll describe the steps followed:
- In the
Office
table, add a new field for UUID (office_uuid
). Since this is a new field, only passnull=True
in the parameters. - We now define a
RunPython
function, which inputs values into the newly created UUID field. - Now, we can alter the
office_uuid
field with the parametersdefault=uuid.uuid4, editable=False, serialize=False
We have successfully created a new office_uuid
field, now comes the task of adding it to Employee
table:
- In the
Employee
table, create aoffice_uuid
field withnull=True
- Define a
RunPython
function, to query withoffice_id
in theOffice
table, and add the correspondingoffice_uuid
- Remove the field
office_id
from theEmployee
table. - Rename the
office_uuid
field tooffice_id
in theEmployee
table.
Now that these changes have been done, we go back to the main table, i.e. Office
again:
- In the
Office
table, remove theoffice_id
field. - Rename the
office_uuid
field tooffice_id
inOffice
. - Alter the new
office_id
by settingprimary_key=True
in the parameters.
Now that we have the updated office_id
field in both the tables, Office
and Employee
, only one step remains:
- In the
Employee
table, alter the fieldoffice_id
and set it as Foreign Key to theOffice
table.
With this, we're done. Please find the code for the steps in the django_pk_to_uuid.py
file.