0

我在 Web api 中有一个“单一”方法,可以进行两次数据库调用

  1. 使用 count() 确保特定对象不存在
  2. 如果对象不存在,则保存它

这里的逻辑显然不是保存已经存在的对象。很简单。当重复的对象开始出现在 db 表中时,问题就来了。然后我意识到我无法控制糟糕的客户呼叫(同时重复呼叫)。

因此,当对该方法的第二次调用恰好发生在具有相同参数(相同对象)的代码块 1) 和 2) 之间时,就会出现问题:

  1. 调用 1 => count() == 0
  2. 调用 2 => count() == 0(它是 0,因为此时第一次调用没有完成处理和保存对象)
  3. 调用 1 => 保存对象
  4. 调用 2 => 保存对象,因为 count() == 0

错误的结果 => 我的表有两行具有相同的值

因此,在“Call 1”代码块完成之前,我不需要处理“Call 2”。

我一直在研究这个很多。一个选项会阻止我正在查询的表,直到方法完成执行(但这会给等式带来新的问题)。

其他人正在谈论使用原子事务,但我不明白如果另一个调用同时运行会有什么帮助。

另一种可能的解决方案是使用 unique_together 所以不可能创建具有相同值的两行(我开始认为这将是最好的选择)

我迷失在茫茫荒野中,试图弄清楚如何解决这个问题。鉴于这个问题很难测试,我想先在这里问。也许我只是错过了一些明显简单的东西......

澄清一下,这就是我判断对象是否已经存在的方式:

    # return error if the follow is already done
    current_follow_query = request.user.follows.filter(influencer=influencer)
    if current_follow_query.count() > 0:
        return Response(status=status.HTTP_204_NO_CONTENT)

    # save the actual follow object
    obj = Follow(follower=request.user, influencer=influencer)
    obj.save()

有任何想法吗?

4

1 回答 1

1

因此,当您通过两个字段定义身份时influencerfollower,那么它们必须是唯一的。unique_together = [('influencer', 'follower')]只需使用约束将其告诉数据库即可。

现在为了保存,您将需要依赖数据库来执行此测试:只需一直保存并在错误发生时处理错误。

from django.db import IntegrityError

try:
    obj = Follow.objects.create(follower=request.user, influencer=influencer)
except IntegrityError:
    # the object already existed!
else:
    # the object was successfully created!
于 2015-08-15T17:06:00.873 回答