【问题标题】:Class based default value for field in Django model inheritance hierarchyDjango模型继承层次结构中字段的基于类的默认值
【发布时间】:2011-04-16 18:20:42
【问题描述】:

如何在以下方案中实现基于类的默认值?我的意思是,我想继承类为“数字”设置不同的默认值:

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

这有效,但只是部分有效,而且表现得很奇怪。在管理界面中,我可以看到仅在第二个或后一页刷新后才设置默认值。第一次尝试时,正在设置None :(

第二种可能性是在每个类中重新定义数字字段,但这似乎不太漂亮。有没有其他办法?

有人可以帮忙吗?

【问题讨论】:

  • 这不会给你一个语法错误number = models.PositiveIntegerField(default=self.create_number())吗?在这种情况下没有self
  • 是的,确实如此——我只是想展示一些与我需要实现的解决方案类似的东西。抱歉误导了。

标签: django dynamic model default field


【解决方案1】:

这里有几个问题。首先,self.method 不起作用。在类主体的上下文中没有 self,这是您声明 PositiveIntegerField 的地方。

其次,传递可调用对象将不起作用,因为可调用对象在编译时被绑定并且在运行时不会更改。所以如果你定义说,

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

我对上述内容进行了一些小改动(由于我没有 PdfPrintable 而将其设为抽象),并且它按预期工作。

【讨论】:

  • 好吧,我知道我使用的剪辑不起作用,我只是想展示我希望它起作用的方式:) 你的解决方案的问题是默认值在创建新对象时的 Django 管理员,这是我需要的必要功能。似乎唯一的解决方案是在每个子模型中重新定义。
【解决方案2】:

通过 default= 执行此操作确实感觉更好,但是您在那里使用的任何东西都无法获得您的班级或特定模型。要让它在管理员等地方正确显示,您可以在 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

【讨论】:

  • 对管理员真的有帮助吗?我的管理面板显示 --- 作为此解决方案的初始值。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-26
  • 1970-01-01
  • 2021-11-29
  • 1970-01-01
  • 2010-10-19
相关资源
最近更新 更多