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

我有一个模型, 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 的方式吗?


桃花长相依
浏览 96回答 1
1回答

米脂

选项 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 ValidationErrordef 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()方法时,将执行所有四个步骤。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python