icn
icn

Reputation: 17876

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

Upvotes: 3

Views: 1977

Answers (1)

exfizik
exfizik

Reputation: 5701

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

Upvotes: 9

Related Questions