我有以下代码:
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 是行不通的(事后看来不应该),因为错误的值将不是唯一的。
有什么想法吗?
您可以覆盖保存方法并在保存前更新值。
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 ...
使用我最后的建议解决并取消类 meta unique_constraint。修改models.py。请参阅代码。对不起,我没有分享“老板”领域。只有行政首长才能成为自己的老板,因此干净的方法行之有效。由于 save 方法,执行头自动更新,clean 方法确保没有多个执行头。