2

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

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

在我根据最后一个车辆数据库记录分配给 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
4

1 回答 1

1

我认为您需要select_for_update锁定行直到事务结束。请注意,尽管它被指定用于多行,但您仍然可以只锁定一行,方法是确保您的filter查询将只返回一个对象。

于 2012-09-14T13:35:26.783 回答