2012-09-12 36 views
2

我有一個表格稱爲車輛,我試圖分配一個唯一的ID給每一個,每次用戶完成一個。分配唯一的ID避免競爭條件

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

試圖避免競態條件(當兩種形式都在同一時間提交),我根據過去的車輛-DB-記錄分配給id字段的初始值後,保存表單我之前再次查詢最後一條記錄的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回報與形式的錯誤錯誤:與此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 
+3

爲什麼你想自己處理獨特的價值?考慮使用autofield https://docs.djangoproject.com/en/dev/topics/db/models/#automatic-primary-key-fields – karthikr

+0

我正在使用遺留數據庫,所以我害怕這是不可能的,或者? – marlen

+0

然後,在視圖中,車輛= Vehicles.objects.all()。order_by(「 - id」)[0] id = vehicles.id + 1沒有幫助。您將不得不在save()方法中進行修改。爲了避免併發性,這裏給出了一些示例:http://stackoverflow.com/questions/320096/django-how-can-i-protect-against-concurrent-modification-of-database-entries – karthikr

回答

1

我想你需要select_for_update其鎖定行,直到最後交易 。請注意,雖然它被指定與許多行一起使用,但仍可以鎖定一行,方法是確保您的filter查詢 將只返回一個對象。