django - 确保创建一个相关对象,竞争条件

时间:2016-07-24 07:06:30

标签: django database object race-condition

我有一张带外键的表。 (我故意在这里使用外键,而不是一对一) 我有一个订单型号:

class Order:
  name = models.CharField(max_length=50)
  user = models.ForeignKey(User)
  active = models.BooleanField(default=True)
  # more fields..

我希望每个用户只存在 这个模型的一个实例。

我有一个简单的表单(和视图)来保存它。我有这段代码:

try:
   instance = Order.objects.get(user=user)
except Order.DoesNotExist:
   instance = None
form = OrderForm(instance=instance)

但是我注意到如果客户端同时发出两个后续请求(注意到我使用了ajax),那么可能会创建两个实例,尽管我有以下验证(假设更新现有的)。 / p>

这非常重要,因为我的其他代码期望每个用户只有一个此模型的实例。我怎样才能在django中强制执行?我在我的观点中尝试了以下内容:

@method_decorator(transaction.atomic, name='dispatch')

但没有奏效。 正如我所说,我不能在这里使用一对一的字段。

2 个答案:

答案 0 :(得分:1)

您可以使用unique_together和可以为空的字段在数据库级别强制执行unicity:

class Order:
    name = models.CharField(max_length=50)
    user = models.ForeignKey(User)
    active = models.NullBooleanField(default=True)

    class Meta:
        unique_together = (('user', 'active'), )

诀窍是针对非活动订单将active设置为None而不是False。由于NULL值在数据库级别不被视为相等,因此用户可能有多个非活动订单但只有一个活动订单。

答案 1 :(得分:0)

您可以为用户设置unique=true。这将确保每个用户只有一个订单。

class Order:
  name = models.CharField(max_length=50)
  user = models.ForeignKey(User, unique=true)
  active = models.BooleanField(default=True)