I need to add an autoinc field that is not the primary key. I am in the process of migrating a very large production database that uses autoincrementing fields to models.UUIDField
. I have been doing a piecewise migration, and all of my relationships are now duplicated with both field types. I'm ready to make the primary key swap, but unfortunately I still need to keep the auto incrementing integer field for old clients as it becomes deprecated.
Since django will not allow me to define an autofield with primary_key=False
(even though this is fully supported at the db layer), i'm looking for a simple solution. My initial strategy would be to simply change the field to models.BigIntegerField('GUID', db_index=True, null=True, unique=True)
and then manually set the default nextval('my_guid_seq'::regclass)
using migrations.RunSQL
. So far so good, except not. It turns out, because of my null=True
declaration, django at the ORM layer is taking over and inserting null
which will not allow defaults at the database layer to do it's job.
The core developers are fast to reject this request because of bad design, which I most definetly agree with, but there are very valid use cases such as this. https://code.djangoproject.com/ticket/8576
I am a very weak django developer so I don't want to get in the weeds metaprogramming at the ORM layer. This is by definition a hack, so i'm looking for the least complex, creative solution that gets me around this limitation
You could subclass AutoField
and override the _check_primary_key
method.
from django.db.models.fields import AutoField
from django.db.models.fields import checks
class AutoFieldNonPrimary(AutoField):
def _check_primary_key(self):
if self.primary_key:
return [
checks.Error(
"AutoFieldNonPrimary must not set primary_key=True.",
obj=self,
id="fields.E100",
)
]
else:
return []
See AutoField
source code here
Edit: Updated Link
I know, changing the primary key to UUID is such a pain.Hence the simple and better solution that I think of is to add another integer field that is auto-incrementing in nature.
Here is my solution:
class ModelName(models.Model):
auto_inc_id = models.IntegerField()
Then override the save model:
def save(self, *args, **kwargs):
self.object_list = ModelName.objects.order_by('auto_inc_id')
if len(self.object_list) == 0: # if there are no objects
self.auto_inc_id = 1
else:
self.auto_inc_id = self.object_list.last().auto_inc_id + 1
super(ModelName, self).save()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With