2015-04-22 103 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

相关问题