[Django]-Django multiple inheritance

2👍

The problem here is that you inherit your model twice, and both the child models have the same name. This results in having twice the same related_name, which is a problem for Django.

Your solution to add

member = models.OneToOneField(Member, related_name="%(app_label)s_%(class)s_related")"

in your MemberExtra model works, but you loose the implicit inheritance magic that Django do to let you access both your models in one:

With your solution you have to do:

from programsite.models import MemberExtra
m = MemberExtra.objects.get(member__full_name = "Foobar")
m.email # -> returns the email of your MemberExtra instance
m.member.b_add # -> returns the address of the inherited member instance

Where, with the Django native inheritance, you can do:

from programsite.models import MemberExtra
m = MemberExtra.objects.get(full_name = "Foobar")
m.email # -> returns the email of your MemberExtra instance
m.b_add # -> returns the address of the inherited member instance

Which is much cleaner in my opinion.

To manage the inheritance, Django actually creates a OneToOneField (https://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance).
This field is called <parentclass>_ptr, member_ptr in you case.


If you manually create a OneToOneField named <parentclass>_ptr, and give it a related_name, Django is still able to find the parent model, and will not complain about identical related_names.

In your case, just add

member_ptr = models.OneToOneField(Member, related_name="%(app_label)s_%(class)s_related")"

in both your MemberExtra model definitions.

This solution works, but is not how it should be done. Django provides a flag parent_link that, when set to true, will tell Django that this is the field that will be used to access the parent class.

So you can add a field

member = models.OneToOneField(Member, parent_link=True, related_name="%(app_label)s_%(class)s_related")"

which will still work if, for some reason, Django needs to rename the default pointer to the parent.

1👍

The related_name for a FK has to be unique. When you have an FK with a default related_name (unspecified), that is inherited by multiple other models, all of the models end up with the same related_name. See the section in the Django docs entitled Be careful with related_name.

The solution is to set the related_name argument of the FK to something like:

prog = models.ForeignKey(Program, verbose_name=_("Program"), related_name="%(app_label)s_%(class)s_related")

Django will then sub the app label and module name into to the string, making the related_name unique for each of the subclasses.

Leave a comment