Rewriting Models
Note
This continues the example defined in the previous page.
As mentioned previously, the separate groups are going to be parent classes for
the new Central
, so we’ll have to define them first. These will be
completely regular models, with one exception: We need to explicitly define
their primary key, and give each of these primary keys a unique name. We can
base this name on the model name; so we’ll have something like:
class Group1(models.Model):
group1_id = models.IntegerField(primary_key=True) # New field
e = models.BooleanField() # This field is taken from Central
f = models.TextField() # This too
# ...
j = models.UUIDField(null=True)
Note that we’re using an IntegerField
, and not an AutoField
, for the primary key; this is because we still
assume that objects of this part of the Central
model will not be created in
isolation, but only as part of a complete Central
object. In such creation,
the primary key value will come from the complete object, and there is no need
to generate it for each of the parts. In fact, an AutoField
should work just as well – one is still allowed
to set the value of an AutoField
explicitly, and that is what a BrokenDownModel
will do for its parents behind the scenes.
We’ll define similarly the next groups:
class Group2(models.Model):
group2_id = models.IntegerField(primary_key=True)
k = models.BooleanField()
# ...
o = models.ForeignKey(SomeOtherModel, null=True, on_delete=models.CASCADE)
# and Group3, and...
class Group4(models.Model):
group4_id = models.IntegerField(primary_key=True)
# ...
z = models.IPV4AddressField()
Now we can finally re-define the original model. We’ll need to import some names from the library:
from bdmodels.fields import VirtualParentLink
from bdmodels.models import BrokenDownModel
and then:
class Central(BrokenDownModel, Group1, Group2, Group3, Group4):
# Add an explicit PK here too
id = models.AutoField(primary_key=True)
# Add links to the parents
group1_ptr = VirtualParentLink(Group1)
group2_ptr = VirtualParentLink(Group2)
group3_ptr = VirtualParentLink(Group3)
group4_ptr = VirtualParentLink(Group4)
# The original core fields we decided to leave in the model
a = models.IntegerField()
b = models.CharField(max_length=100)
c = models.DateTimeField()
d = models.DateField()
Note that we had to define the primary key explicitly here as well. This is because Django’s default behavior for MTI is to use the parent-link to the first parent as the PK of the child. We do not want this.
The VirtualPrentLink
fields
defined explicitly, replace similarly-named OneToOneField
fields which Django would generate, by
default, to connect a child model with its MTI parents. They differ from such
fields by all using the id
column in the database – regular parent-link
OneToOneField
fields would each
define their own column, although for our use case these columns would all be
holding the same value (same as id
).
With these definitions, our app is essentially ready to work against a database
where the Central
model has been broken down (up to some limitations, see
below). But we still have to bring our database to this state. It is now time to
talk about…