Django ORM 模型“保存”方法和竞争条件/ACID 隔离

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

如果我们检查以下代码:

class SomeModel(models.Model):
    ...
    def save(self, *args, **kwargs):
        self.validate_unique()
        super().save()

    def validate_unique(self, *args, **kwargs):
        super().validate_unique(*args, **kwargs)
        
        # Doing an ORM query on the model with *filter* on the model attributes & an associated model, 
        # and if exist - dont create a new instance, if not - create a new instance.
        is_duplicated = SomeModel.objects.filter(name=given_name_from_user, attribute_from_associated_model=some_attr)
        if is_duplicated:
             raise Exception("go wrong")
        # Else - continue to save

现在,它可以与开发服务器一起使用,但不能与gunicorn或uvicorn等生产服务器一起使用,因为save方法保证了我们的原子性,但不能保证隔离,对吧?

为了保证隔离,我们应该在视图级别使用“get_or_create”?

我有什么地方搞错了吗? 任何评论都会有帮助,谢谢!

django django-models concurrency
1个回答
0
投票

您应该使用

UniqueConstraint
。将阻止创建具有相同值的特定字段的实例。

此外,

get_or_create
也不会创建具有与提供的值相同的实例。 但这两种策略之间存在差异。如果您使用
UniqureConstraint
,它将防止您以任何方式创建实例时出现重复记录。但在
get_or_create
策略中,只有在调用时才会防止重复实例。

class SomeModel(models.Model):
    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=["name", "attribute_from_associated_model"], name="unique_constraint_name"
        )
    ]
© www.soinside.com 2019 - 2024. All rights reserved.