Consider model “First”
class First(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
other = models.CharField(max_length=50)
and model “Second”
class Second(models.Model):
somefield = models.CharField(max_length=255)
prime = models.ForeignKey(First, on_delete=models.CASCADE)
Question:
Is it possible to perform a non-destructive change of fieldname in Second
(say, from prime
to first
)? So far, makemigration
is requiring that I provide a default for the new name (first
), which implies that it is deleting prime
to replace it with first
. That means, I will lose data. How do I get around this? More so, How do I provide a dud default for UUID primary keys?
When you run makemigrations
, then it should detect that this is a field rename - when I try this, I get the question:
Was second.prime renamed to second.first (a ForeignKey)? [y/N]
If you’re not getting this question, then I’d try making this change independently of all other changes, to see if Django will recognize this as a rename.
1 Like
I get the prompts for ordinary fields, the affected ones are either OneToOne or ForeignKey fields.
Instead I get the following:
It is impossible to add a non-nullable field 'first' to second without specifying a default. This is because the database needs something to populate existing rows.
Please select a fix:
1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
2) Quit and manually define a default value in models.py.
Select an option:
This is scary. It is not recognizing that prime
is being replaced by first
. Imagining what I am about to lose.
Notice that the prompt I posted specifically identifies this as a foreign key. (I directly copied your models into a test project.)
Again, what do you get if you only try to rename that one field? Is there the chance that Django is getting confused with other changes being made? Are there other renames happening with the same names of other fields?
Note, running makemigrations itself is not going to delete any data. You can run makemigrations, then use the sqlmigrate command to see exactly what is going to happen with that migration. If you don’t like what it’s going to do, delete the migration file.
1 Like
I see the problem now. I took your advise and isolated changes (rather than having many changes on a model at a time). The problem is with db_column
parameter in prime.
my version has:
prime = models.ForeignKey(First, on_delete=models.CASCADE, db_column="prime")
and I also changed the value of the db_column
parameter. It does not appear that I can avoid loses if the name of the column is changing at database level. Should I brace up for dumping and restoring directly at database level?
I would try making this as two separate migrations. Create one migration where you change the field name, and then a second migration to change the column name.
1 Like
I will try this shortly. I am also observing that running makemigrations
with --dry-run
overlooks issues regarding non-provision of defaults for non-nullable fields. Would be nice to see all possible outcomes before performing the migration