django 模型字段中的唯一值

问题描述 投票:0回答:2

我有以下代码:

from django.db import models
from django.contrib.auth import get_user_model

User = get_user_model()


class Employee(models.Model):
    employee = models.OneToOneField(User, on_delete=models.CASCADE)
    boss = models.ForeignKey(
        "self",
        on_delete=models.CASCADE,
        null=True,
        blank=True),
    )
    executive_head = models.BooleanField(
        default=False,
        help_text=_("e.g. Chief Executive Officer or Managing Director."),
    )
    job_title = models.CharField(max_length=100)

    class Meta:
        ordering = ["id"]
        constraints = [
            UniqueConstraint(
                fields=["executive_head"],
                name="only_one_executive_head",
                condition=Q(executive_head=True),
            )
        ]

    def __str__(self):
        return f"{ self.employee }"

    def save(self, *args, **kwargs):

        if self.employee == self.boss:
            self.executive_head = True
        else:
            self.executive_head = False

    def clean(self):
        if Employee.objects.filter(executive_head=True) and 
           self.employee == self.boss:
            raise ValidationError(
                {"executive_head": _("There can only be one executive          
                  head.")
                }
            )

我希望看到的是 executive_head 字段中只有一个值应该为真。不应该有一个以上的行政首长。

在 Meta 类中使用 unique_together 是行不通的(事后看来不应该),因为错误的值将不是唯一的。

有什么想法吗?

django unique
2个回答
0
投票

您可以覆盖保存方法并在保存前更新值。

class Employee(models.Model):
    employee = models.OneToOneField(User, on_delete=models.CASCADE)
    executive_head = models.BooleanField(
        default=False,
        help_text=_("e.g. Chief Executive Officer or Managing Director."),
    )
    job_title = models.CharField(max_length=100)

    def __str__(self):
        return f"{ self.employee }"

    def save(self, *args, **kwargs):
        """
        Make sure only one executive_head is set to true
        """
        if self.executive_head:
            Employee.objects.filter(executive_head=True).update(executive_head=False)
        super().save(*args, **kwargs)

或者您可以在特定字段上使用部分唯一索引:

class Employee(models.Model):
    ...
    
    class Meta:
        constraints = [
            UniqueConstraint(
                fields=["executive_head"],
                name='only_one_executive_head',
                condition=Q(executive_head=True)
            )
        ]

这将引发

IntegrityError
,因为 unique_together 也会这样做。您可以像这样在视图中捕获异常:

from django.db import IntegrityError

try:
    Employee.objects.create(
        employee=employee,
        executive_head=True,
        job_title="Job title"
    )
except IntegrityError:
    # handle the IntegrityError with frontend message ...

0
投票

使用我最后的建议解决并取消类 meta unique_constraint。修改models.py。请参阅代码。对不起,我没有分享“老板”领域。只有行政首长才能成为自己的老板,因此干净的方法行之有效。由于 save 方法,执行头自动更新,clean 方法确保没有多个执行头。

© www.soinside.com 2019 - 2024. All rights reserved.