如何将可调用函数设置为 AutoField 默认属性?

How to set a callable function to AutoField default attribute?

我正在尝试覆盖我的模型的 pk 以使用随机生成器。

这是模型字段:

pk = models.AutoField(auto_created=True, primary_key=True, verbose_name='ID', default=genkey)

和密钥生成器:

def genkey():
    return random.randrange(1,142857)

所以,我想让自动字段尽可能多地执行genkey函数,直到它得到一个未使用的键。是否有我没有找到的属性,或者我是否需要在生成器中对其进行编码(通过获取所有使用的键)?

我的主要目标是使生成器尽可能通用,而不是为每个模型定义自定义生成器。

一个 AutoField [Django-doc] 就像文档中说的那样:

An IntegerField that automatically increments according to available IDs. You usually won't need to use this directly; a primary key field will automatically be added to your model if you don’t specify otherwise.

因此它是一个IntegerField [Django-doc],因此我们可以简单地使用一个IntegerField来代替,like:

class SomeModel(models.Model):
    pk = models.<b>IntegerField</b>(<b>editable=False,</b> auto_created=True, primary_key=True, verbose_name='ID', default=genkey)
    # ...

因此,在 AutoField 上指定默认值与 AutoField 的做法有点矛盾。如果你用 editable=False [Django-doc] 创建一个 IntegerField,要确保至少在默认情况下,它不会包含在 ModelForm 中。这本质上就是主键的作用。

经过一些研究和测试,我最终创建了一个 class。

class RandomIDKey(models.Model):
    id = models.IntegerField(
        auto_created=True,
        primary_key=True,
        serialize=False,
        verbose_name='ID',
        unique=True,
        db_index=True,
        editable=False
    )

    def save(self, *args, **kwargs):
        if not self.id:
            self.id = genkey(type(self))
        super().save(*args, **kwargs)

    class Meta:
        abstract = True

具有 public 功能:

def genkey(model):
    generated_key = random.randrange(1, 2147483648)
    if model.objects.filter(pk=generated_key).exists():
        generated_key = genkey(model)
    return generated_key

使用 AutoField 是个坏主意,因为该字段不是 auto-generated 数据库,因此 IntegerField