-
-
Save smcoll/8bb867dc631433c01fd0 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*- | |
from __future__ import unicode_literals | |
import uuid | |
from django.db import migrations, models | |
def fill_mymodel_uuid(apps, schema_editor): | |
db_alias = schema_editor.connection.alias | |
MyModel = apps.get_model('myapp', 'MyModel') | |
for obj in MyModel.objects.using(db_alias).all(): | |
obj.uuid = uuid.uuid4() | |
obj.save() | |
class Migration(migrations.Migration): | |
""" Change model with integer pk to UUID pk. This migration presumes there | |
are no db constraints (foreign keys) to this table. | |
""" | |
dependencies = [ | |
# ... | |
] | |
operations = [ | |
migrations.AddField( | |
model_name='mymodel', | |
name='uuid', | |
field=models.UUIDField(null=True), | |
), | |
migrations.RunPython(fill_mymodel_uuid, migrations.RunPython.noop), | |
migrations.AlterField( | |
model_name='mymodel', | |
name='uuid', | |
field=models.UUIDField(default=uuid.uuid4, serialize=False, editable=False, unique=True), | |
), | |
migrations.RemoveField('MyModel', 'id'), | |
migrations.RenameField( | |
model_name='mymodel', | |
old_name='uuid', | |
new_name='id' | |
), | |
migrations.AlterField( | |
model_name='mymodel', | |
name='id', | |
field=models.UUIDField(primary_key=True, default=uuid.uuid4, serialize=False, editable=False), | |
), | |
] |
how do you deal with foreign keys?
Thank you bro!
@PFischbeck: a primary key has to be unique. Don't know how you plan to use it as a primary key without uniqueness constraint.
Removing the
unique=True
in lines 39 and 53 made the migration reversible for me. For some reason, this allows the primary key constraint on the UUIDField to be dropped.
Hi, I came across this because I am migrating models. First, thank you for the gist. Second, from the documentation, primary_key=True implies null=False and unique=True, so I am guessing that was creating some conflict with your implicit 'unique=True'.
Thanks for this!
Thanks @PFischbeck and @marodrig - not sure how i missed those comments long ago. Gist is updated.
Thanks for this @smcoll. Why is the migrations.RunPython.noop
necessary?
@zlove i believe that otherwise, the RunPython
operation is not reversible.
how do you deal with foreign keys?
I have the following issue: 'Cannot add foreign key constraint'. It happens on the migrations.RemoveField('MyModel', 'id') step. Don't know how to fix it, Django 1.11.
@gabn88 that's trickier. Off the top of my head, i think you have to do something like this, with each step as its own migration file:
- add the new UUID column to this model, fill it with unique values, make it NOTNULL/unique (operations 1-3 in this gist)
- (for each referencing model) add a new UUID column which stores a UUID (nullable at first)
- fill that column with the UUID value corresponding to the integer ID value for the referenced object
- update the new UUID field on the referencing model so it's a foreign key type (using
to_field
), and make it notnull (adding the constraint) - drop the original foreign key column on the referencing model
- drop the original id field of this model (operation 4 in this gist)
Notice that i left out the last two operations... if you want an id
column and corresponding foo_id
columns on the related tables (rather than uuid
and foo_uuid
columns), then i think you have to drop the foreign key constraints altogether, do the column renaming, and then add the constraints back afterward.
Please someone correct me if i'm wrong there.
@smcoll @gabn88 I have uploaded code, which ensures that the foreign key relations are maintained. Please check it out here: https://github.com/sharshub/django-pk-to-uuid.
@smcoll, thanks for this, it helped with my migrations. I used this to build upon and implement my code.
@sharshub Thanks für this really good help!
Have you or (anyone else here) done it for many2many relations as well? I have no idea how to change the id's in the intermediate tables.
Removing the
unique=True
in lines 39 and 53 made the migration reversible for me. For some reason, this allows the primary key constraint on the UUIDField to be dropped.