Sometimes, old design decisions comes back to bite you. This is one of those tales.
A project I’m working on had a Django model similar to this:
code = models.CharField(max_length=2, primary_key=True)
name = models.CharField(max_length=100)
and it was used by other models such as:
code = models.CharField(max_length=4, primary_key=True)
municipality = models.ForeignKey(Municipality)
And all was good, until we needed to expand the municipality model to support different countries, and thus a single unique field with only the
code - which may collide across countries, was not enough.
For all the modern parts of the code base we use
UUIDs as the primary key,
so we wanted to migrate the primary key of
Municipality to a
retaining all the relations.
As of September 2017, Django does not support migrating primary keys in any nice manner, so we’re on our own here.
We tried a lot of magic solutions, but we always got stuck with the migrations system not being able to detect and handle the changes nicely.
After some research and quite a bit of trial and error, we settled on the following approach. It has some drawbacks I’ll get back to, but works reasonable well.