Seamless Polymorphic Inheritance for Django Models

class polymorphic.models.PolymorphicModel(*args, **kwargs)

Bases: django.db.models.base.Model

Abstract base class that provides polymorphic behaviour for any model directly or indirectly derived from it.

PolymorphicModel declares one field for internal use (polymorphic_ctype) and provides a polymorphic manager as the default manager (and as ‘objects’).

Parameters:polymorphic_ctype (ForeignKey to ContentType) – Polymorphic ctype
__init__(*args, **kwargs)

Replace Django’s inheritance accessor member functions for our model (self.__class__) with our own versions. We monkey patch them until a patch can be added to Django (which would probably be very small and make all of this obsolete).

If we have inheritance of the form ModelA -> ModelB ->ModelC then Django creates accessors like this: - ModelA: modelb - ModelB: modela_ptr, modelb, modelc - ModelC: modela_ptr, modelb, modelb_ptr, modelc

These accessors allow Django (and everyone else) to travel up and down the inheritance tree for the db object at hand.

The original Django accessors use our polymorphic manager. But they should not. So we replace them with our own accessors that use our appropriate base_objects manager.


Upcast an object to it’s actual type.

If a non-polymorphic manager (like base_objects) has been used to retrieve objects, then the complete object with it’s real class/type and all fields may be retrieved with this method.


Each method call executes one db query (if necessary). Use the get_real_instances() to upcast a complete list in a single efficient query.


Return the actual model type of the object.

If a non-polymorphic manager (like base_objects) has been used to retrieve objects, then the real class/type of these objects may be determined using this method.


Make sure the polymorphic_ctype value is correctly set on this model.

save(*args, **kwargs)

Calls pre_save_polymorphic() and saves the model.


Model field: polymorphic ctype, accesses the ContentType model.