Reputation: 8570
I have a simple model::
class HasUUID(models.Model):
name = models.CharField(max_length=10)
batchid = models.UUIDField(default=uuid.uuid4(), unique=True)
running makemigrations gives me the migration::
operations = [
migrations.CreateModel(
name='HasUUID',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=10)),
('batchid', models.UUIDField(default=uuid.UUID('79a2d9fe-e1d0-4d4b-884f-fad0bfb14f0f'), unique=True)),
],
),
]
Running migrate gives me the new table no problem. But I can run makemigrations again and I get::
operations = [
migrations.AlterField(
model_name='hasuuid',
name='batchid',
field=models.UUIDField(default=uuid.UUID('3b96231c-5848-430b-aa90-b6e41b11fd0a'), unique=True),
),
]
and while I have lived with this for a while, manually removing the unnecessary code, I need to resolve it.
so I think, make the default a separate function in the migrations as shown in various examples::
def create_uuid(apps, schema_editor):
m = apps.get_model('web', 'HasUUID')
for inst in m.objects.all():
inst.batchid = uuid.uuid4()
inst.save()
...
migrations.CreateModel(
name='HasUUID',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=10)),
('batchid', models.UUIDField(blank=True, null=True)),
],
),
migrations.RunPython(create_uuid),
migrations.AlterField(
model_name='hasuuid2',
name='batchid',
field=models.UUIDField(default=uuid.uuid4, unique=True)
),
same problem. So I tried making the default a separate function in the model::
def create_uuid():
return uuid.uuid4()
class HasUUID2(models.Model):
name = models.CharField(max_length=10)
batchid = models.UUIDField(default=create_uuid(), unique=True)
and this gets me this migration::
migrations.CreateModel(
name='HasUUID3',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=10)),
('batchid', models.UUIDField(default=uuid.UUID('335c3651-b04e-4ed8-a91d-f2da3f53dd8f'), unique=True)),
],
),
and again, keeps generating new migrations. I've also tried without the unique = True.
I'm out of ideas. There must be some settings or code elsewhere as I have used UUID fields before and I cannot find a similar problem on stackoverflow. Any suggestions?
Upvotes: 3
Views: 973
Reputation: 476740
You should pass the callable as default, not the result of a call, like:
class HasUUID(models.Model):
name = models.CharField(max_length=10)
batchid = models.UUIDField(default=uuid.uuid4, unique=True)
Notice that there are no paratheses here to make the call, we thus pass a reference to the uuid4
function itself.
The default=
value is not a specific UUID (that is determined when you start the server), it should be a value that is determined when you create a new object (without specifying the batchid
yourself).
By passing a callable, Django will understand that the default is the result of a call to the callable, and it will encode that in the migration. By calling the function, you retrieve the result of the call, and each time you run makemigrations
, Django will think that you changed your mind on what should be the default value (it will first think you want to use '3b96231c-5848-430b-aa90-b6e41b11fd0a'
as default, and later that you want to use '335c3651-b04e-4ed8-a91d-f2da3f53dd8f'
). By passing a callable, the value you pass as default remains the same.
Upvotes: 9