分配唯一ID以避免竞争条件

时间:2012-09-12 18:19:02

标签: django

我有一个名为Vehicles的表单,我试图为每个表单分配一个唯一的ID,每次用户完成一个。

class Vehicles(models.Model):
     id = models.DecimalField(primary_key=True, unique=True)

尝试避免竞争条件(当两个表单同时提交时)在我根据最后一个vehicle-db-record分配给id字段的初始值之后,在保存表单之前我再次查询db对于最后一条记录的id。或多或少我这样做:

def vehicle(request):
    vehicles= Vehicles.objects.all().order_by("-id")[0]
    id = vehicles.id+1

    if request.method == 'POST':
        form = VehiclesForm(data=request.POST)

        if form.is_valid():
            vehicles= Vehicles.objects.all().order_by("-id")[0]
            id = vehicles.id+1
            temp = form.save(new_veh_id=id)
            return render_to_response('success.html', locals(), context_instance= RequestContext(request))
    else:
        form = VehiclesForm(initial={'id': id})
    return render_to_response('insertVehicle.html', locals(), context_instance= RequestContext(request))

并在表单中覆盖保存方法:

    def save(self, *args, **kwargs):
        commit = kwargs.pop('commit', True)
        new_veh_id = kwargs.pop('new_veh_id', None)
        instance = super(VehiclesForm, self).save(*args, commit = False, **kwargs)

        if id is not None: instance.id = new_veh_id
        if commit:
            instance.save()
        return instance

但is_valid返回false,表单错误:具有此ID的车辆已存在。 我完全使用这种做法与另一个模型和形式(相同的字段)和它的作用就像一个魅力,表单传递验证尽管相同的ID,它在最后提交的表单中更改它。任何人都可以帮我这个或建议一个更好的解决方案来实现这个功能?我所做的可能是某种'习惯'。

编辑:我也试过了,但is_valid再次失败

    def clean(self):
        cleaned_data = super(VehiclesForm, self).clean()
        id = unicode(self.cleaned_data.get('id'))

        vehicles= Vehicles.objects.all().order_by("-id")[0]
        id = vehicles.id+1
        cleaned_data[id] = id

        return cleaned_data

1 个答案:

答案 0 :(得分:1)

我认为你需要select_for_update来锁定行直到结束 交易。请注意,虽然它被指定与许多人合作 行,您仍然可以通过确保filter查询来锁定一行 将仅返回一个对象。