Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

better django model design

Here is my situation:

I have a django model:

class Invoice(models.Model):
    invoiceid = models.CharField(max_length=20)
    totalamount = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    downpayment = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    subtotal = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    tax = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    amountdue = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    payment = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    originaldate = models.DateTimeField()
    changedate = models.DateTimeField()
    version = models.IntegerField(default=1)
    operator = models.CharField(max_length=20)

and I have a pretty much identical model to keep all updated history. This InvoiceHistory basically just keeps all updates.

class InvoiceHistory(models.Model):
    invoiceid = models.CharField(max_length=20)
    totalamount = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    downpayment = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    subtotal = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    tax = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    amountdue = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    payment = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    originaldate = models.DateTimeField()
    changedate = models.DateTimeField()
    version = models.IntegerField()
    operator = models.CharField(max_length=20)

I know this design is not very efficient and error-prone . Whenever business logic changes I need to update both models and it is easy to forget to change the other one. Is there a better django model design for this problem?

Thanks

like image 715
icn Avatar asked Feb 02 '26 22:02

icn


1 Answers

You could create an abstract base class and have both models inherit from it:

class InvoiceAbstract(models.Model):
    invoiceid = models.CharField(max_length=20)
    totalamount = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    downpayment = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    subtotal = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    tax = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    amountdue = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    payment = models.DecimalField(max_digits=15,decimal_places=2,default=0)
    originaldate = models.DateTimeField()
    changedate = models.DateTimeField()
    version = models.IntegerField(default=1)
    operator = models.CharField(max_length=20)
    class Meta:
        abstract = True

class Invoice(InvoiceAbstract):
    pass
class InvoiceHistory(InvoiceAbstract):
    pass

https://docs.djangoproject.com/en/dev/topics/db/models/#abstract-base-classes

like image 165
exfizik Avatar answered Feb 04 '26 14:02

exfizik