Django模型:默认外键选择

时间:2019-10-20 18:54:49

标签: python django django-models

我有一个Type模型类,如下所示:

class Type(models.Model):
    ENVIRONMENT = 'A'
    HUMANENV = 'B'
    HUMAN = 'C'
    ANIMAL = 'D'
    UNKNOWN = 'H'
    TYPE_CHOICES = [
        (ENVIRONMENT, 'Environment'),
        (HUMANENV, "Human-related Environment"),
        (HUMAN, 'Human'),
        (ANIMAL, 'Animal'),
        (UNKNOWN, 'Unknown'),
    ]
    code = models.CharField(max_length=1, choices=TYPE_CHOICES, unique=True)

    class Meta:
        ordering = ['code']

    def __str__(self):
        return self.get_code_display()

和另一个Sample模型,其中一个字段是Type模型的外键,如下所示:

class Sample(models.Model):
    sample_id = models.CharField(max_length=20, unique=True)
    type = models.ForeignKey("Type", on_delete=models.CASCADE, blank=True, default=get_default_type())

    class Meta:
        ordering = ["sample_id"]

    def __str__(self):
        return self.sample_id

其中get_default_type是一个函数,它返回默认Type模型实例的pk:

def get_default_type():
    return Type.objects.get(code="H").id

问题是当我运行Sample.objects.create(sample_id =“ some_id”)时,它给了我错误

IntegrityError: null value in column "type_id" violates not-null constraint
DETAIL:  Failing row contains (28113, some_id, null).

如错误消息第二行所示,type_id为null,而不是get_default_type函数返回的pk。

我尝试为外键设置null = True,当我这样做时,我可以创建Sample模型实例,但是使用None类型而不是所需的Unknown类型。我该如何解决?

1 个答案:

答案 0 :(得分:0)

两种解决方案:

覆盖经理

通过此response,您可以在管理器中使用get_by_natural_key

managers.py

from django.db import models
class TypeManager(models.Manager):
    """Enable fixtures using self.sigla instead of `id`"""

    def get_by_natural_key(self, code):
        return self.get(code=code)
class Type(models.Model):
    #.... Declare your model here
    objects = Type()

或...

更改您的pk!

class Type(models.Model):
    #.... Declare your model here
    code = models.CharField(max_length=1, choices=TYPE_CHOICES, unique=True, primary_key=True)

无论哪种方式,在您相关的模型声明中:

class Sample(models.Model):
    type = models.ForeignKey("Type", on_delete=models.CASCADE, blank=True, default='H')

    class Meta:
        ordering = ["sample_id"]

    def __str__(self):
        return self.sample_id

请注意:请注意type。 这是一个受保护的关键字,不应使用。