In same cases different models could have same fields and same procedures in the product life cycle. To handle these similarities without having code repetition inheritance could be used. Instead of inheriting a whole class, mixin design pattern offers us to inherit (or some says include) some methods and attributes. Let's see an example:
class PostableMixin(models.Model): class Meta: abstract=True sender_name = models.CharField(max_length=128) sender_address = models.CharField(max_length=255) receiver_name = models.CharField(max_length=128) receiver_address = models.CharField(max_length=255) post_datetime = models.DateTimeField(auto_now_add=True) delivery_datetime = models.DateTimeField(null=True) notes = models.TextField(max_length=500) class Envelope(PostableMixin): ENVELOPE_COMMERCIAL = 1 ENVELOPE_BOOKLET = 2 ENVELOPE_CATALOG = 3 ENVELOPE_TYPES = ( (ENVELOPE_COMMERCIAL, 'Commercial'), (ENVELOPE_BOOKLET, 'Booklet'), (ENVELOPE_CATALOG, 'Catalog'), ) envelope_type = models.PositiveSmallIntegerField(choices=ENVELOPE_TYPES) class Package(PostableMixin): weight = models.DecimalField(max_digits=6, decimal_places=2) width = models.DecimalField(max_digits=5, decimal_places=2) height = models.DecimalField(max_digits=5, decimal_places=2) depth = models.DecimalField(max_digits=5, decimal_places=2)
To turn a model into an abstract class, you will need to mention
abstract=True in its inner
Django does not create any tables for abstract models in the database.
However for the models
Package, corresponding tables would be created in the database.
Furthermore the fields some model methods will be needed at more than one models.
Thus these methods could be added to mixins to prevent code repetition.
For example if we create a method to set delivery date to
PostableMixin it will be accesible from both of its children:
class PostableMixin(models.Model): class Meta: abstract=True ... ... def set_delivery_datetime(self, dt=None): if dt is None: from django.utils.timezone import now dt = now() self.delivery_datetime = dt self.save()
This method could be used as following on the children:
>> envelope = Envelope.objects.get(pk=1) >> envelope.set_delivery_datetime() >> pack = Package.objects.get(pk=1) >> pack.set_delivery_datetime()