【问题标题】:Django form update optimistic locking, version basedDjango 表单更新乐观锁定,基于版本
【发布时间】:2023-01-12 20:45:37
【问题描述】:

我有 Django 模型和视图,如下所示:(+mysql db)


class MyModel(models.Model): 
    name = models.CharField(max_length=100)
    version = models.IntegerField(default=1, editable=False)

def updateModel(request, id): 
    toUpdate = MyModel.objects.get(pk=id)    
    if request.method=='POST':
        form = MyModelForm(request.POST,  instance=toUpdate)
        if form.is_valid(): 
        actual =  MyModel.objects.get(pk=id)    
        if (actual.version == form.instance.version):
            form.instance.version = form.instance.version+1
            form.save()
            return redirect('somewhere')
        else:
            #some error
            
    form = MyModelForm(instance=toUpdate)
    return render(request, 'somwhere2/createupdate.html', {'form':form})

场景是:- 当前模型值:name="aaa", version=1,

2 个用户打开编辑表单,第一个用户将名称“aaa”更改为“bbb”并保存,第二个用户将名称“aaa”更改为“ccc”并保存。结果是“ccc”,但我想要一些消息/版本冲突消息......问题是......没有冲突,因为即使第二个用户仍然可以看到“aaa”,而在数据库中有“bbb”已经...但是在单击 POST 按钮后,值首先更新为 bbb,并且版本已更新,因此代码无法看到,user2 在旧版本上工作...:(

我想要那种版本控制机制来防止这种情况,但我无法实现它......

如何实施?

我已经阅读了所有关于 django 乐观锁定等的内容,但无法实现,

【问题讨论】:

    标签: django locking version optimistic


    【解决方案1】:

    我认为使用select_for_update() 可能会解决您的问题。 查看this article

    我在想这样的事情:

    def updateModel(request, id): 
        toUpdate = MyModel.objects.get(pk=id)    
        if request.method=='POST':
            form = MyModelForm(request.POST,  instance=toUpdate)
            if form.is_valid(): 
                with transaction.atomic():
                    try:
                         actual =  MyModel.objects.filter(pk=id).select_for_update(nowait=True).get()
                    except OperationalError:
                        # raise some error 
                    if (actual.version == form.instance.version):
                        form.instance.version = form.instance.version+1
                        form.save()
                        return redirect('somewhere')
                    else:
                        #some error
                
        form = MyModelForm(instance=toUpdate)
        return render(request, 'somwhere2/createupdate.html', {'form':form})
    

    【讨论】:

    • 嗯,但是 user1 更新了模型,所以不是事务,不存在锁,但是 user2 仍然能够覆盖 user1 的更改,不知道它...... toUpdate = MyModel.objects.get(pk=id) - 也许这是一个问题,即 - 在 POST,模型从 db 更新,所以它不再是“aaa”,而是已经更改为“bbb”,....但我不知道以任何其他方式实现它
    • 是否要保持版本编号清晰,以便在两次并发更改后从版本 12 升级到版本 14(而不是版本 13)?或者您是否试图阻止第二个用户进行更改?
    • 如果是后者,您可以尝试将 form.initialactual 进行比较,看看它们是否匹配,否则会引发错误。
    猜你喜欢
    • 2011-08-18
    • 2016-05-30
    • 2017-06-07
    • 1970-01-01
    • 1970-01-01
    • 2010-09-12
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多