Django 模型继承层次结构中字段的基于类的默认值
在以下方案中如何实现基于类的默认值?我的意思是,我想继承的类以不同的方式设置“number”的默认值:
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
我查看了 这个 stackoverflow 问题,但它没有解决同样的问题。我认为唯一可行的是重载 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
被设置:(
第二种可能性是在每个类中重新定义数字字段,但这看起来不太漂亮。还有其他方法吗?
有人可以帮忙吗?
How can one accomplish class-based default value in following scheme? I mean, I would like to inherited classes set default value for "number" differently:
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
I have looked at this stackoverflow question, but it doesn't address the same problem. The only thing I thought would work was overloading OrderDocumentBase
's __init__
method like this:
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
This works, but only partially and behaves quite wierdly. In admin interface, I can see the default being set only after second or latter page refresh. On first try, None
is being set :(
Second possibility is redefinition of number field in each class, but that doesn't seem too much pretty. Is there any other way?
Can someone help?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
通过 default= 执行此操作确实感觉更好,但是您在那里使用的任何内容都无法获取您的类或特定模型。为了让它在管理员等地方正确显示,您可以在 init() 而不是 save() 中设置它。
It does feel nicer to do this via default=, but anything you use there doesn't have a way to get at your class or specific model. To have it show up properly in places like the admin, you could set it in init() instead of save().
这里有几个问题。首先,self.method 不起作用。类主体的上下文中没有
self
,这是您声明PositiveIntegerField
的地方。其次,传递可调用对象将不起作用,因为可调用对象在编译时绑定并且在运行时不会更改。因此,如果您定义,
所有
Invoice
实例仍将使用0
作为默认值。我能想到的解决这个问题的一种方法是重写
save()
方法。您可以检查number
是否尚未提供,并在保存之前将其设置为默认值。我用一个小改动测试了上面的内容(使
OrderDocumentBase
抽象,因为我没有PdfPrintable
),并且它按预期工作。There are a couple of problems here. First, the
self.method
is not going to work. There is noself
in the context of the body of the class, which is where you are declaring thePositiveIntegerField
.Second, passing a callable will not work as the callable gets bound at compile time and does not change at runtime. So if you define say,
All
Invoice
instances will still get0
as default value.One way I can think of to tackle this is to override the
save()
method. You can check if thenumber
has not been supplied and set it to a default before saving.I tested the above with a small change (made
OrderDocumentBase
abstract as I did not havePdfPrintable
) and it worked as expected.