A django application that provides a simple way to retrieve models type casted to their original ContentType.
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.
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
Inspired by a post of Jeff Elmores.
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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| django_polymodels-1.8.1.tar.gz | 14.6 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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.