I'm working on a project and problem is I've already created models with simple ID column but now my requirements are changed and I want to replace ID field (model) with UUID field I just updated my model:
uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)
but when I run my migrations I got an error
django.db.utils.OperationalError: (1829, "Cannot drop column 'id': needed in a foreign key constraint
Please guide me how can I perform this migration?
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)
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)
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,
)
to_field
which tell django this foreign key is not pointing to default pk
fieldblank = null = True
Base
you should add this temp field5- 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
base_uuid
fields in all models should contain a valid data6- 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)
9- in all related models (models which you have added base_uuid
fields) update the field
_uuid
from column name) (make this a individual Migration!)relate_name
field name (remove _uuid
from related name)blank = null = true
if necessaryto_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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With