How can I support AutoField(primary_key=False) in django?

被刻印的时光 ゝ 提交于 2020-08-24 08:18:42

问题


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


回答1:


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




回答2:


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.sheets) is 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()


来源:https://stackoverflow.com/questions/37709163/how-can-i-support-autofieldprimary-key-false-in-django

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!