如何在 Django 中支持 AutoField(primary_key=False)?

Rya*_*huk 6 django autofield

我需要添加一个不是主键的 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,所以我正在寻找最简单、最有创意的解决方案来解决这个限制

roo*_*oob 5

您可以子类化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 []
Run Code Online (Sandbox Code Playgroud)

在此处查看AutoField源代码

编辑:更新链接

  • 如果没有一个可能的后果的例子,我认为这不足以诋毁他的回答。没有什么能阻止 AUTO INCREMENT 功能在数据库层被非主键控,所以我无法预见一个问题。 (4认同)
  • 覆盖后,makemigrations 错误就会停止,但当您实际尝试迁移时,我们会收到错误。当您使用 sqlmigrate 输出时,您可以看到甚至 AutoFieldNonPrimary 列也会被标记为 PRIMARY,因此在数据库级别不允许创建两个主键! (3认同)
  • 错误检查是有原因的,绕过它很可能会导致问题。我对 Django ORM 的内部结构不够熟悉,无法预测可能的后果,但我会寻找另一种解决方法。 (2认同)