Quickstart¶
Install the project using:
pip install django-polymorphic
Update the settings file:
INSTALLED_APPS += (
'polymorphic',
'django.contrib.contenttypes',
)
The current release of django-polymorphic supports Django 2.2 - 4.0 and Python 3.6+.
Making Your Models Polymorphic¶
Use PolymorphicModel
instead of Django’s models.Model
, like so:
from polymorphic.models import PolymorphicModel
class Project(PolymorphicModel):
topic = models.CharField(max_length=30)
class ArtProject(Project):
artist = models.CharField(max_length=30)
class ResearchProject(Project):
supervisor = models.CharField(max_length=30)
All models inheriting from your polymorphic models will be polymorphic as well.
Using Polymorphic Models¶
Create some objects:
>>> Project.objects.create(topic="Department Party")
>>> ArtProject.objects.create(topic="Painting with Tim", artist="T. Turner")
>>> ResearchProject.objects.create(topic="Swallow Aerodynamics", supervisor="Dr. Winter")
Get polymorphic query results:
>>> Project.objects.all()
[ <Project: id 1, topic "Department Party">,
<ArtProject: id 2, topic "Painting with Tim", artist "T. Turner">,
<ResearchProject: id 3, topic "Swallow Aerodynamics", supervisor "Dr. Winter"> ]
Use instance_of
or not_instance_of
for narrowing the result to specific subtypes:
>>> Project.objects.instance_of(ArtProject)
[ <ArtProject: id 2, topic "Painting with Tim", artist "T. Turner"> ]
>>> Project.objects.instance_of(ArtProject) | Project.objects.instance_of(ResearchProject)
[ <ArtProject: id 2, topic "Painting with Tim", artist "T. Turner">,
<ResearchProject: id 3, topic "Swallow Aerodynamics", supervisor "Dr. Winter"> ]
Polymorphic filtering: Get all projects where Mr. Turner is involved as an artist or supervisor (note the three underscores):
>>> Project.objects.filter(Q(ArtProject___artist='T. Turner') | Q(ResearchProject___supervisor='T. Turner'))
[ <ArtProject: id 2, topic "Painting with Tim", artist "T. Turner">,
<ResearchProject: id 4, topic "Color Use in Late Cubism", supervisor "T. Turner"> ]
This is basically all you need to know, as django-polymorphic mostly works fully automatic and just delivers the expected results.
Note: When using the dumpdata
management command on polymorphic tables
(or any table that has a reference to ContentType
),
include the --natural
flag in the arguments. This makes sure the
ContentType
models will be referenced by name
instead of their primary key as that changes between Django instances.
Note
While django-polymorphic makes subclassed models easy to use in Django,
we still encourage to use them with caution. Each subclassed model will require
Django to perform an INNER JOIN
to fetch the model fields from the database.
While taking this in mind, there are valid reasons for using subclassed models.
That’s what this library is designed for!