Class based default value for field in Django model inheritance hierarchy

孤街醉人 提交于 2019-12-05 10:41:17

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().

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

There are a couple of problems here. First, the self.method is not going to work. There is no self in the context of the body of the class, which is where you are declaring the PositiveIntegerField.

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,

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

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

All Invoice instances will still get 0 as default value.

One way I can think of to tackle this is to override the save() method. You can check if the number has not been supplied and set it to a default before saving.

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

I tested the above with a small change (made OrderDocumentBase abstract as I did not have PdfPrintable) and it worked as expected.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!