首页 > 解决方案 > 在 Django 中防止重复的 XMLHttpRequests

问题描述

在我的应用程序中,单击按钮会向我的服务器发送 XHR 请求以升级帐户并向用户收费。

def upgradeView(request):
    if request.user.upgraded == False:
         billAccount(request.user.id)
    else: 
         return HttpRequests('Already billed')
    request.user.upgraded = True
    request.user.save()
    return HttpResponse('OK!')

我可以使用 Javascript 更改按钮,以便在用户单击一次后将其禁用。如何在服务器端确认用户不能同时提交 5 个 XHR 请求并最终被计费 5 次?我有一个手动检查,检查他们是否已经计费,但是如果 billAccount 函数需要几秒钟,并且多个请求能够billAccount在用户能够设置为升级之前触发调用怎么办?

越想越觉得不可能阻止多个请求滑入。即使billAccount调用是一毫秒,这仍然足够多个请求进来的时间。

标签: djangoconcurrencylocking

解决方案


答案是使用select_for_updatetransaction.atomic()用于悲观锁定,以及“no_wait”参数。这样做是为了防止任何其他进程在该对象被锁定时选择该对象。这是一个更深入的好资源。

以下是我认为您可以锁定该行的方式,以便多个事务不会同时发生:

def upgradeView(request):
    with transaction.atomic():
        u = Users.objects.select_for_update(nowait=True).filter(pk=request.user.pk)
        if u.upgraded == False:
             billAccount(u.id)
        else: 
             return HttpRequests('Already billed')
        u.upgraded = True
        u.save()
        return HttpResponse('OK!')

推荐阅读