简体   繁体   English

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

[英]Check for unique constraint inside the save method

I have a model on which the unique_together parameter is not working.我有一个 model,其 unique_together 参数不起作用。 The reason is that most of the times the "client_repr" variable is set on the save() method.原因是大多数时候“client_repr”变量是在 save() 方法上设置的。 If someone creates a task with the same ('client_repr', 'task_type'... ) combination the model won't detect it because the "client_repr" value is null until the end of the save() method.如果有人使用相同的 ('client_repr', 'task_type'...) 组合创建任务,model 将不会检测到它,因为在 save() 方法结束之前“client_repr”值为 null。

How can i call for a unique constraint verification inside the save() method?我如何在 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)

I know i could just make a search (ex: if Task.objects.get(...): ) but is it the most django-pythonic way?我知道我可以进行搜索(例如:如果 Task.objects.get(...): )但它是最 django-pythonic 的方式吗?

Option 1: Using clean()选项 1:使用clean()

It's not directly what you asked, but it's generally more django-friendly and does not require weird things like overriding save()这不是你直接问的,但它通常对 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

Since this custom clean() is called before django calls validate_unique() , it should fulfill your requirements.由于此自定义clean()在 django 调用validate_unique()之前被调用,因此它应该满足您的要求。

See the details in the official documentation.请参阅官方文档中的详细信息

Option 2: Continue doing everything in save()选项 2:继续在save()中做所有事情

To check unique constraints, you can do the following:要检查唯一约束,您可以执行以下操作:

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)

Note:笔记:

  • doing only self.validate_unique() does not guarantee, that the updated earlier in save() values are good and don't violate something else只做self.validate_unique()并不能保证之前更新的save()值是好的并且不违反其他内容
  • self.full_clean() is safer, but will be slightly slower (how slow - depends on the validators you have) self.full_clean()更安全,但会稍微慢一些(有多慢——取决于你拥有的验证器)

Documentation文档

Django documentation says : Django 文档说

There are three steps involved in validating a model:验证 model 涉及三个步骤:

  • Validate the model fields - Model.clean_fields()验证 model 字段 - Model.clean_fields()
  • Validate the model as a whole - Model.clean()整体验证 model - Model.clean()
  • Validate the field uniqueness - Model.validate_unique()验证字段唯一性 - Model.validate_unique()

All three steps are performed when you call a model's full_clean() method.当您调用模型的 full_clean() 方法时,将执行所有三个步骤。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM