here are the list of actions that you need to do
1 - add the new uuid
field to model (I name this model Base
) then generate migration files
uuid = models.UUIDField(default=uuid4, blank=True, null=True)
- note that uuid is not primarykey yet
- note that
blank = null =True
2- in this step you should populate uuid
field with valid data. you should write a data migration file for Base
model. please check docs for more info
your forwards method should be something like this:
for item in Base.objects.all():
item.uuid = uuid4()
item.save()
3- change uuid field to this and generate migrations
uuid = models.UUIDField(default=uuid4, unique=True)
- note that uuid is not primarykey yet, but it's unique now
4 - for other models which are pointing to Base
model you should add a new foreignkey pointing to uuid field
assumig your default relation to Base model is something like this
base = models.ForeignKey(
Base, on_delete=models.PROTECT, related_name='base'
)
you should add a temprory field like this
base_uuid = models.ForeignKey(
Base,
on_delete=models.PROTECT,
related_name='base_uuid',
to_field='uuid',
blank=True,
null=True,
)
- note that I have explicitly defined
to_field
which tell django this foreign key is not pointing to default pk
field
- you should keep old foreign key field
- also set
blank = null = True
- for all foreignkeys/manytomanyfield pointing to
Base
you should add this temp field
5- in this step you should create a data migration file,
in this data migration file you need to fill all base_uuid
fields with valid data (based on old base
field) your migration code can be something like this
for item in RelatedModel.objects.all():
item.base_uuid_id = item.base.uuid
- after this step all
base_uuid
fields in all models should contain a valid data
6- in all related models drop related field (keep the new base_uuid
field but discard old related field) and generate a migration file
7- delete the db_constraint on all FK fields - this is needed, because django will connect through the unique constraint from base_uuid
which will be dropped if we change uuid
to pk.
base_uuid = models.ForeignKey(
Base,
on_delete=models.PROTECT,
related_name='base_uuid',
to_field='uuid',
blank=True,
null=True,
db_constraint=False
)
8- in Base
model change uuid field and generate a migration file
uuid = models.UUIDField(default=uuid4, primary_key=True)
- uuid is now a primary key!
9- in all related models (models which you have added base_uuid
fields) update the field
- rename field name (remove
_uuid
from column name) (make this a individual Migration!)
- change
relate_name
field name (remove _uuid
from related name)
- remove
blank = null = true
if necessary
- remove
to_field='uuid'
argument (you don't need that any more)
Very Important Note: run these code with test data and create a full backup from your database before running this code on your actual data