8

我需要添加一个不是主键的 autoinc 字段。我正在将一个使用自动递增字段的大型生产数据库迁移到models.UUIDField. 我一直在进行分段迁移,现在我的所有关系都与两种字段类型重复。我已准备好进行主键交换,但不幸的是,我仍然需要为旧客户端保留自动递增整数字段,因为它已被弃用。

由于 django 不允许我定义一个自动字段primary_key=False(即使这在 db 层完全支持),我正在寻找一个简单的解决方案。我最初的策略是简单地将字段更改为models.BigIntegerField('GUID', db_index=True, null=True, unique=True),然后nextval('my_guid_seq'::regclass)使用migrations.RunSQL. 到目前为止一切顺利,除了没有。事实证明,由于我的null=True声明,ORM 层的 django 正在接管并插入null,这将不允许数据库层的默认值来完成它的工作。

由于糟糕的设计,核心开发人员很快就拒绝了这个请求,我非常同意,但也有非常有效的用例,例如这样。https://code.djangoproject.com/ticket/8576

我是一个非常弱的 django 开发人员,所以我不想在 ORM 层陷入杂草元编程。根据定义,这是一个 hack,所以我正在寻找最简单、最有创意的解决方案,让我绕过这个限制

4

3 回答 3

6

您可以子类AutoField化并覆盖该_check_primary_key方法。

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 []

在此处查看AutoField源代码

编辑:更新链接

于 2016-06-08T18:29:42.227 回答
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.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()
 
于 2019-09-19T07:37:36.300 回答
-2

无法将此格式化为评论,但修改@Abhimanyu 的答案以使保存方法更简洁(并且只发出一个查询)。同型号属性:

class ModelName(models.Model):
    auto_inc_id = models.IntegerField()

这是模型上的保存方法:

def save(self, *args, **kwargs):
    self.auto_inc_id = ModelName.objects.all().count() + 1
    super(ModelName, self).save()
于 2021-01-17T20:19:09.083 回答