Django migrations, backfilling data

Another very common migration pattern I have come across over the years, is what to do when adding a required (non-nullable) field to an existing model. Let's set the scene, say you have a model called Post that looks as roughly follows:

class Post(models.Model):
  title = models.Charfield(...)
  content = models.TextField(...)
  author = models.ForeignKey(User, ...)
  slug = modelds.SlugField(...)

and you have been tasked with updating the URL to replace the the use of the primary key id with an external identifier. One might think the adding the following field defintion would be sufficient:

  uuid = models.UUIDField(default=uuid.uuid4, null=False, editable=False)

Unfortunately this will throw an error during the migration since, the callable in the default will return the same uuid for each row. Instead you will need to follow these three steps:

  1. Add the field with null=True so:
 uuid = models.UUIDField(default=uuid.uuid4, null=True, editable=True)
  1. Add a data migration to manually assign a uuid4 value to each existing instance of the model (simple loop and save will be sufficient here)
  2. Update the field to make null=False and editable=False will will leave your field in the desired result.

And your done! and freely available to use this field in your URL without worrying about the value being null.