【问题标题】:How to set a callable function to AutoField default attribute?如何将可调用函数设置为 AutoField 默认属性?
【发布时间】:2019-06-28 10:22:37
【问题描述】:

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

这是模型字段:

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

和密钥生成器:

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

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

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

【问题讨论】:

  • AutoField 的想法是 数据库 将自动创建一个 id。
  • 我知道,它可以是IntegerField 或其他,我在这里使用AutoField,因为它是默认的pk 字段类型。

标签: django django-models parameters default


【解决方案1】:

如文档所述,AutoField [Django-doc] 是:

IntegerField 根据可用 ID 自动递增。您通常不需要直接使用它;如果您没有另外指定,主键字段将自动添加到您的模型中。

因此它是一个IntegerField [Django-doc],因此我们可以简单地使用IntegerField,就像这样:

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

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

【讨论】:

  • 为什么一定要blank=True?默认设置为实例化,因此该字段永远不会为空。
  • @DanielRoseman:您不需要将其设置为 blank=True,但 AutoField 将其设置为空白 (github.com/django/django/blob/master/django/db/models/fields/…)。可能是因为否则它将出现在 ModelForm 中,而 pk 通常不是用户应该创建/更新的东西。
  • 不,那是因为你说 AutoField 没有默认值,它是由数据库在保存时设置的,所以如果空白为 False,那么模型将永远无效。这不是这里的情况,我们确实有一个默认值。
  • @DanielRoseman:嗯……是的。也许editable=False 更好?
【解决方案2】:

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

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

具有公共功能:

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 是个坏主意,因为该字段不是由数据库自动生成的,因此使用 IntegerField

【讨论】:

    猜你喜欢
    • 2019-07-04
    • 1970-01-01
    • 2022-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-08
    • 1970-01-01
    • 2023-03-15
    相关资源
    最近更新 更多