Defining models with specializations¶
Overview
This document describes the customizations you will need to make to your Django models to make the specialization code work. There’s not too much to bear in mind, so the switch should be easy!
Example models¶
Let us consider the models we defined in Introduction:
from django.db import models
from djeneralize.models import BaseGeneralizationModel
from djeneralize.fields import SpecializedForeignKey
#{ General model
class WritingImplement(BaseGeneralizationModel):
name = models.CharField(max_length=30)
length = models.IntegerField()
holder = SpecializedForeignKey(
'WritingImplementHolder', null=True, blank=True)
def __unicode__(self):
return self.name
#{ Direct children of WritingImplement, i.e. first specialization
class Pencil(WritingImplement):
lead = models.CharField(max_length=2) # i.e. HB, B2, H5
class Meta:
specialization = 'pencil'
class Pen(WritingImplement):
ink_colour = models.CharField(max_length=30)
class Meta:
specialization = 'pen'
#{ Grand-children of WritingImplement, i.e. second degree of specialization
class FountainPen(Pen):
nib_width = models.DecimalField(max_digits=3, decimal_places=2)
class Meta:
specialization = 'fountain_pen'
class BallPointPen(Pen):
replaceable_insert = models.BooleanField(default=False)
class Meta:
specialization = 'ballpoint_pen'
#{ Writing implement holders general model
class WritingImplementHolder(BaseGeneralizationModel):
name = models.CharField(max_length=30)
def __unicode__(self):
return self.name
#{ Writing implement holders specializations
class StationaryCupboard(WritingImplementHolder):
volume = models.FloatField()
class Meta:
specialization = 'stationary_cupboard'
class PencilCase(WritingImplementHolder):
colour = models.CharField(max_length=30)
class Meta:
specialization = 'pencil_case'
#}
Derive your model from BaseGeneralizationModel
¶
The top-level model is derived from djeneralize.models.BaseGeneralizationModel
and not django.db.models.Model
. Just make sure this class is
imported at the top of the module and that’s the inheritance done!
Set up the specialization for your models¶
You must explicitly declare the specialization that your model exhibits. In most cases the naming can be similar to the class name, but only alphanumeric characters are accepted here.
This declaration should always be done in the inner class Meta
declaration.
Note
The top-most sub-class of BaseGeneralizedModel does not require and, in fact, forbids the declaration of a specialization.
These specializations are used by djeneralize
to keep track of the
relationships between the general case and the specializations. The model
calculates a “path” for each specialization with the most general case being
assigned the /
path. This value is stored on the specialization_type field,
so be careful when altering this field.
Warning
If the inheritance scheme changes for your models you will need to
create a database migration to ensure that the specialization_type
field
is correctly mapped to the new structure of your inheritance.