Seamless Polymorphic Inheritance for Django Models
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
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_ctypevalue is correctly set on this model.