2010-09-24 22 views
4

如何在以下方案中实现基于类的默认值?我的意思是,我想继承类设置默认值“数量”是不同的:Django模型继承层次结构中基于类的默认值

class OrderDocumentBase(PdfPrintable): 
    number = models.PositiveIntegerField(default=self.create_number()) 

    @classmethod 
    def create_number(cls): 
     raise NotImplementedError 

class Invoice(OrderDocumentBase): 
    @classmethod 
    def create_number(cls): 
     return 1 

class CreditAdvice(OrderDocumentBase): 
    @classmethod 
    def create_number(cls): 
     return 2 

我已经看过this stackoverflow question,但它并没有解决同样的问题。我以为会工作的唯一的事是超载OrderDocumentBase__init__方法是这样的:

def __init__(self, *args, **kwargs): 
    """ 
    Overload __init__ to enable dynamic set of default to number 
    """ 
    super(OrderDocumentBase, self).__init__(*args, **kwargs) 
    number_field = filter(lambda x: x.name == 'number', self._meta.fields)[0] 
    number = self.__class__.create_number() 
    number_field.default = number 

这工作,但只是部分,并且表现相当wierdly。在管理界面中,我可以看到仅在第二次或后一页刷新后才设置默认值。在第一次尝试,None被设置:(

第二种可能性是在每个班级数场的重新定义,但是这似乎并没有太多的漂亮。有没有其他办法?

有人能帮助?

+0

这不会给你一个语法错误'number = models.PositiveIntegerField(default = self.create_number())'?在这方面没有“自我”。 – 2010-09-24 12:24:20

+0

是的,它的确如此 - 我只想表现出类似于我需要实现的解决方案。对不起,误导了剪辑。 – xaralis 2010-09-26 12:24:43

回答

6

通过默认=这样做确实感觉更好,但是您使用的任何东西都无法获得您的课程或特定模型。为了让它在像admin这样的地方正确显示,您可以将它设置为init()而不是save()。

class OrderDocumentBase(PdfPrintable): 
    number = models.PositiveIntegerField() 

    def __init__(self, *args, **kwargs): 
     super(OrderDocumentBase, self).__init__(*args, **kwargs) 
     if not self.pk and not self.number: 
      self.number = self.DEFAULT_NUMBER 

class Invoice(OrderDocumentBase): 
    DEFAULT_NUMBER = 2 

class CreditAdvice(OrderDocumentBase): 
    DEFAULT_NUMBER = 3 
1

有几个问题在这里。首先,self.method是行不通的。有一个在类的主体,这是你在哪里声明PositiveIntegerField

二的情况下没有self,传递可调用函数将无法正常工作,因为可调用函数在com处受到约束堆积时间并且在运行时不会改变。所以,如果你定义说,

class OrderDocumentBase(PdfPrintable): 
    create_number = lambda: return 0 
    number = models.PositiveIntegerField(default=create_number) 

class Invoice(OrderDocumentBase): 
    create_number = lambda: return 1 

所有Invoice情况下仍然会得到0为默认值。

我可以想到解决这个问题的一种方法是覆盖save()方法。您可以检查number是否尚未提供,并在保存前将其设置为默认值。

class OrderDocumentBase(PdfPrintable): 
    number = models.PositiveIntegerField() 

    def save(self, *args, **kwargs): 
     if not self.number: 
      self.number = self.DEFAULT 
     super(OrderDocumentBase, self).save(*args, **kwargs) 

class Invoice(OrderDocumentBase): 
    DEFAULT = 2 

class CreditAdvice(OrderDocumentBase): 
    DEFAULT = 3 

我测试了上面的微小变化(由OrderDocumentBase抽象,因为我没有PdfPrintable)和它的工作如预期。

+0

嗯,我知道我用过的剪断不起作用,我只是想表现出我希望它能起作用的方式:) 解决方案的问题在于,在创建新的时候,Django admin中将不会显示默认值对象,这是我需要的必要功能。似乎唯一的解决方案是在每个儿童模型中重新定义。 – xaralis 2010-09-26 12:21:30