2015-04-22 137 views
2

我實現在Django模型中的字段,要求缺省值設置在Django模型字段默認值更好的辦法

def get_default_value(): 
    a = MyModel.objects.aggregate(max_id=Max('id')) 
    return get_unique_value_based_on_num(a['max_id'] or 0) 

class MyModel: 
    default_value_field = CharField(default=get_default_value) 

雖然我可能是錯在這下面的函數,我擔心這實現可在比賽狀態。

有沒有更好的方法來做到這一點?可能是使用F對象或其他東西?

回答

1

爲避免競爭條件,最好讓數據庫處理表的完整性,這是數據庫的一個要求。

爲此,請捕獲通過保存模型實例引發的任何IntegrityError,並在失敗時再次嘗試使用不同的值。

from django.db import IntegrityError, models, transaction 


def get_default_value(): 
    a = MyModel.objects.aggregate(max_id=Max('id')) 
    return get_unique_value_based_on_num(a['max_id'] or 0) 

class MyModel(models.Model): 
    # Have unicity enforced at database level with unique=True. 
    default_value_field = models.CharField(max_length=200, unique=True) 

    def save(self): 
     if not self.default_value_field: 
      max_tries = 100 # Choose a sensible value! 
      for i in range(max_tries): 
       try: 
        self.default_value_field = get_default_value() 

        # Atomic block to rollback transaction in case of IntegrityError. 
        with transaction.atomic(): 
         super(MyModel, self).save() 
         break 
       except IntegrityError: 
        # default_value_field is not unique, try again with a new value. 
        continue 
      else: 
       # Max tries reached, raise. 
       raise IntegrityError('Could not save model because etc...') 
     else: 
      super(MyModel, self).save(*args, **kwargs) 
+0

我目前檢查出'select_for_update',看看是否會工作了。我想這也是一個有效的替代方法,因此接受它。循環內的'save'後面不會有'break'嗎? – sagarchalise

+0

@sagarchalise你是絕對正確的。 – aumo

+0

@sagarchalise我不知道'select_for_update',但它似乎正是你要找的,如果你設法用它來解決你的問題,你應該發佈一個答案並接受它。 – aumo

相關問題