views:

47

answers:

1

I have this models:

class BillHeader(models.Model):
    billno = models.IntegerField(primary_key=True, blank=True)

class BillData(models.Model):
    price = models.DecimalField(_('Price'), max_digits=12, decimal_places=2)
    amount = models.DecimalField(_('Amount'), max_digits=6, decimal_places=2)

    [... rest of the model ...]

    class Meta:
        abstract = True

class BillFooter(models.Model):
    total = models.DecimalField(_('Total'), max_digits=12, decimal_places=2)

    [... rest of the model ...]

    class Meta:
        abstract = True

BillData and BillFooter are common to every BillHeader so I've marked them as abstract. Can I do class BillHeader(BillData, BillFooter) or I'm doing something wrong?

I also thought about doing BillData the main one, and BillHeader BillFooter abstract. I don't have any experience on doing data models (at least not complex ones) and I'm a bit lost. What would you recommend?

+3  A: 

Yes, a Django model can inherit from as many abstract base classes as you like, as long as they don't result in an ambiguous "model resolution order". Think of inheritance as a chain... each class you inherit from is a link in the chain. Inheriting from two base classes is just adding two links to the chain instead of one.

In other words, if your abstract base classes inherit from models.Model, then don't try to inherit from both the abstract base class and models.Model in your Bill class. models.Model is already in the inheritance chain, so inheriting from it causes chaos in the chain of base classes.

As to how I would structure these classes, I would create a model called Bill that inherited from BillHeader, BillData, and BillFooter. The reason for this is that I like my Django models to represent discrete objects (e.g. Bill, Article, BlogPost, Photo, etc.)

However, the point of abstract base classes is to be able to add a level of abstraction to common fields and methods so that multiple classes can inherit from them. If you're just creating a Bill class it's somewhat meaningless. If, however, you had Bill, and UnpaidBill, and PaidBill... all of those would have common fields that should appear on all of them and you can save yourself a lot of trouble by abstracting to an ABC.

Hopefully that offers a little insight to what ABC's and inheritance are good for.

Gabriel Hurley
+1 for the explanation about discrete objects. However, I still have a doubt, if I create a Bill class, can it be empty? I mean, with no fields, only inheriting from the ABC's?
Oscar Carballal
it can indeed. you would just write `pass` indented under the class.
Gabriel Hurley