The default class for a field in a Django model inheritance hierarchy

How can the default default value be executed in the following diagram? I mean, I would like inherited classes to set the default value for "number" in different ways:

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 reviewed https://stackoverflow.com/a/3126326/2126 , but this does not address the same issue. The only thing that I thought would work is to overload the OrderDocumentBase __init__ method as follows:

 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 

It works, but only partially and behaves rather strangely. In the admin interface, I see that the default value is set only after updating the second or last page. On the first attempt, None installed: (

The second option is to redefine the number field in each class, but that doesn't seem too big. Is there another way?

Can anyone help?

+4
source share
2 answers

This is really nice to do by default =, but everything you use there does not have the ability to get into your class or specific model. To make it display correctly in places like admin, you can set it to 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 
+6
source

There are a couple of issues here. Firstly, self.method will not work. In the context of the class body, there is no self where you declare PositiveIntegerField .

Secondly, the transfer of the called call will not be performed because the called gets the binding at compile time and does not change at run time. 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 instances of Invoice will still get 0 as the default value.

One way I can solve this is to override the save() method. You can check if number was not, and set it to 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 checked above with a slight change (made OrderDocumentBase abstract since I did not have PdfPrintable ) and it worked as expected.

+1
source

All Articles