为了账号安全,请及时绑定邮箱和手机立即绑定

检查保存方法内的唯一约束

检查保存方法内的唯一约束

桃花长相依 2023-10-18 15:32:54
我有一个模型, unique_together 参数不起作用。原因是大多数时候“client_repr”变量是在 save() 方法上设置的。如果有人使用相同的 ('client_repr', 'task_type'...) 组合创建任务,模型将不会检测到它,因为在 save() 方法结束之前“client_repr”值为 null。如何在 save() 方法中调用唯一约束验证?class Task(models.Model):    client = models.ForeignKey(Client, related_name = 'tasks', on_delete = models.CASCADE)    b_client = models.ForeignKey(BClient, related_name = 'tasks', on_delete = models.CASCADE, null = True, blank = True)    client_repr = models.CharField(max_length = 100, null = True, blank = True)    task_type = models.CharField(max_length = 100)    task_description = models.CharField(max_length = 100)    department = models.ForeignKey(Department, related_name = 'tasks', on_delete = models.CASCADE)    extra_fields = models.ManyToManyField(ExtraField, blank = True)    spot = models.BooleanField(default = False)    class Meta:        unique_together = (('client_repr', 'task_type', 'task_description', 'department'), )    def __str__(self):        return ' | '.join([f'{self.client_repr}', f'{self.task_description}', f'{self.task_type}'])    def save(self, *args, **kwargs):        if not self.b_client:            self.client_repr = str(self.client)        else:            self.client_repr = str(self.b_client)        super().save(*args, **kwargs)我知道我可以进行搜索(例如: if Task.objects.get(...): ),但这是最 django-pythonic 的方式吗?
查看完整描述

1 回答

?
米脂

TA贡献1836条经验 获得超3个赞

选项 1:使用clean()

这不是你直接要求的,但它通常对 django 更友好,并且不需要像重写这样奇怪的东西save()


class Task(Model):


    def clean():

        # your code starts here

        if not self.b_client:

            self.client_repr = str(self.client)

        else:

            self.client_repr = str(self.b_client)

        # your code ends here

由于此自定义clean()是在django 调用之前validate_unique()调用的,因此它应该满足您的要求。


选项 2:继续执行中的所有操作save()

要检查唯一约束,您可以执行以下操作:


from django.core.exceptions import ValidationError


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

    ...  # your code that automatically sets some fields

    try:

        self.validate_unique()

        # self.full_clean()  # <- alternatively, can use this to validate **everything**, see my comments below

    except ValidationError:

        # failed

        # that's up to you what to do in this case

        # you cannot just re-raise the ValidationError because Django doesn't expect ValidationError happening inside of save()

    super().save(*args, **kwargs)

笔记:


只做并self.validate_unique()不能保证早期更新的save()值是好的并且不会违反其他内容

self.full_clean()更安全,但会稍微慢一些(多慢 - 取决于您拥有的验证器)

文档

Django文档说:

验证模型涉及四个步骤:

  • 验证模型字段 - Model.clean_fields()

  • 验证整个模型 - Model.clean()

  • 验证字段唯一性 - Model.validate_unique()

  • 验证约束 - Model.validate_constraints()

当您调用模型的full_clean()方法时,将执行所有四个步骤。


查看完整回答
反对 回复 2023-10-18
  • 1 回答
  • 0 关注
  • 95 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信