Django模型如何将类方法结果设为字段默认值?
Django模型中动态获取类对象数量作为字段默认值的问题
我在用Django Models开发,想获取类的对象数量并作为模型字段的参数传入,先写了测试代码尝试排查问题:
class someclass: somevar = 'somevalue' def retrieve1(): return somevar def retrieve2(self): return self.somevar def retrieve3(): return someclass.somevar # 报错:NameError: name 'somevar' is not defined value1 = retrieve1() # 报错:TypeError: retrieve2() missing 1 required positional argument: 'self' value2 = retrieve2() # 报错:NameError: name 'someclass' is not defined value3 = retrieve3()
我还尝试通过__init__把somevar作为实例属性传入,还是不行:
class someclass: def __init__(self): self.somevar = 'somevalue' # 报错:NameError: name 'self' is not defined value = self.somevar
包括用@classmethod、@staticmethod装饰器的方法也试过,都没解决。
以下是我实际开发中遇到问题的代码:
class Box(models.Model): # 想获取当前类所有对象的数量,加1作为默认值 def defaultOrder(): return len(Box.objects.all()) + 1 name = models.CharField(max_length=100, unique=True) order = models.IntegerField( blank=False, unique=True, # 这里要传入默认值 default= defaultOrder() ) end_days = models.IntegerField(blank=False) end_hours = models.IntegerField(blank=False) end_minutes = models.IntegerField(blank=False) def __str__(self): return self.name
我希望能像在类外部操作一样调用类相关内容,请问问题出在哪?
解决方案
核心问题是类定义阶段的执行逻辑:在类还没完全定义完成时,类内部的顶级代码就已经执行了。这时候直接调用defaultOrder(),不仅Box类还没创建完毕,而且Django模型类此时还未和数据库建立有效关联。
另外,Django字段的default参数支持传入可调用对象(即函数本身,不用加括号),而不是直接传函数执行后的结果。调整后的代码如下:
class Box(models.Model): @staticmethod def defaultOrder(): # 用count()比len(Box.objects.all())更高效,直接查询数据库计数 return Box.objects.count() + 1 name = models.CharField(max_length=100, unique=True) order = models.IntegerField( blank=False, unique=True, # 传入函数本身,不要加括号 default=defaultOrder ) end_days = models.IntegerField(blank=False) end_hours = models.IntegerField(blank=False) end_minutes = models.IntegerField(blank=False) def __str__(self): return self.name
测试代码报错的原因解释
- 类定义阶段,所有顶级变量(比如
value1/2/3)都会立即执行:retrieve1里直接用somevar,类定义阶段的作用域无法直接访问类变量,需要通过类名调用,但此时类还未定义完成,所以retrieve3也报错retrieve2是实例方法,必须实例化类后才能调用,类定义阶段不存在self实例,所以报错__init__里的self.somevar是实例属性,类级别的value无法直接访问实例属性,因为类定义阶段还没有任何实例
内容的提问来源于stack exchange,提问作者at_Root
相关产品推荐
相关产品推荐

