Skip to main content

A django application that provides a simple way to retrieve models type casted to their original ContentType.

Build Status https://coveralls.io/repos/charettes/django-polymodels/badge.svg?branch=master&service=github

Installation

>>> pip install django-polymodels

Make sure 'django.contrib.contenttypes' and 'polymodels' are in your INSTALLED_APPS

INSTALLED_APPS += ('django.contrib.contenttypes', 'polymodels')

Usage

Subclass PolymorphicModel, an abstract model class.

from django.db import models
from polymodels.models import PolymorphicModel

class Animal(PolymorphicModel):
    name = models.CharField(max_length=255)

    def __str__(self):
        return self.name

class Mammal(Animal):
    pass

class Dog(Mammal):
    pass

class Reptile(Animal):
    pass

class Snake(Reptile):
    class Meta:
        proxy = True

Objects are created the same way as usual and their associated ContentType is saved automatically:

>>> animal = Animal.objects.create(name='animal')
>>> mammal = Mammal.objects.create(name='mammal')
>>> reptile = Reptile.objects.create(name='reptile')
>>> snake = Snake.objects.create(name='snake')

To retreive type casted instances from the Animal.objects manager you just have to use the select_subclasses method.

>>> Animal.objects.select_subclasses()
[<Animal: animal>, <Mammal: mammal>, <Reptile: reptile>, <Snake: snake>]

You can also retreive a subset of the subclasses by passing them as arguments to select_subclass.

>>> Animal.objects.select_subclasses(Reptile)
[<Reptile: reptile>, <Snake: snake>]

Or directly from subclasses managers.

>>> Reptile.objects.select_subclasses(Snake)
[<Snake: snake>]

Note that you can also retrieve original results by avoiding the select_subclasses call.

>>> Animal.objects.all()
[<Animal: animal>, <Animal: mammal>, <Animal: reptile>, <Animal: snake>]

It’s also possible to select only instances of the model to which the manager is attached by using the exclude_subclasses method.

>>> Mammal.objects.all()
[<Mammal: mammal>]

Each instance of PolymorphicModel has a type_cast method that knows how to convert itself to the correct ContentType.

>>> animal_snake = Animal.objects.get(pk=snake.pk)
<Animal: snake>
>>> animal_snake.type_cast()
<Snake: snake>
>>> animal_snake.type_cast(Reptile)
<Reptile: snake>

If the PolymorphicModel.content_type fields conflicts with one of your existing fields you just have to subclass polymodels.models.BasePolymorphicModel and specify which field polymodels should use instead by defining a CONTENT_TYPE_FIELD attribute on your model. This field must be a ForeignKey to ContentType.

from django.contrib.contenttypes.models import ContentType
from django.db import models
from polymodels.models import BasePolymorphicModel

class MyModel(BasePolymorphicModel):
    CONTENT_TYPE_FIELD = 'polymorphic_ct'
    polymorphic_ct = models.ForeignKey(ContentType)

How it works

Under the hood select_subclasses calls seleted_related to avoid unnecessary queries and filter if you pass some classes to it. On queryset iteration, the fetched instanced are converted to their correct type by calling BasePolymorphicModel.type_cast. Note that those lookups are cached on class creation to avoid computing them on every single query.

Note of the author

I’m aware there’s already plenty of existing projects tackling the whole model-inheritance-type-casting-thing such as django-polymorphic. However I wanted to implement this feature in a lightweight way: no __metaclass__ or __init__ overrides while using django’s public API as much as possible. In the end, this was really just an extraction of django-mutant’s own mecanism of handling this since I needed it as a standalone app for another project.

Contribute

If you happen to encounter a bug or would like to suggest a feature addition please file an issue or create a pull request containing tests.

Credits

Metadata

Release files for django-polymodels 1.8.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-polymodels 1.8.1
File Size Uploaded Provenance
django_polymodels-1.8.1.tar.gz 14.6 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for django-polymodels 1.8.1
File Interpreter ABI Platform
django_polymodels-1.8.1-py2.py3-none-any.whl Python 3, Python 2 none any Details

Total release size: 25.8 kB

Release files / django_polymodels-1.8.1.tar.gz

Download URL django_polymodels-1.8.1.tar.gz
Size 14.6 kB
Tags Source
SHA-256 checksum
How to use checksums
bb2956192fe13bbd0f32f05f76d6b688d045cbb2ece76c40fff06926d6b3f497
BLAKE2b-256 checksum
How to use checksums
4881c93c602b2c65830d00ab13cf5540026df3213d38dd79cc4bf82c27595762
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.9.21

Release files / django_polymodels-1.8.1-py2.py3-none-any.whl

Download URL django_polymodels-1.8.1-py2.py3-none-any.whl
Size 11.2 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
4fc16ac535a87fd9b3f6e7ccf7f9da509978d024f36da59ed250dbb6bf11fa75
BLAKE2b-256 checksum
How to use checksums
67815bd124652083ebcd38bd7cfa38d0dfb20aee55b0559f95847dfbef8036b4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.9.21

Security for django-polymodels 1.8.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page