Skip to main content
 首页 » 编程设计

python之在 Django 模型字段中设置默认值的更好方法

2025年05月04日42daizhj

我正在 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 对象或其他东西?

请您参考如下方法:

为避免竞争条件,最好让数据库处理表的完整性,这是数据库的目的之一。

为此,请捕获通过保存模型实例引发的任何 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)