{"id":2931,"library":"django-polymorphic","title":"Django Polymorphic","description":"Django Polymorphic simplifies the use of inherited models in Django projects by automatically returning subclass instances when querying a base model. It enhances Django's multi-table inheritance to provide a seamless polymorphic experience in the ORM and admin interface. The library is actively maintained by the Jazzband community and is currently at version 4.11.2, with regular updates addressing bugs and adding features like comprehensive type annotations.","status":"active","version":"4.11.2","language":"en","source_language":"en","source_url":"https://github.com/jazzband/django-polymorphic","tags":["django","orm","polymorphism","models","inheritance","admin"],"install":[{"cmd":"pip install django-polymorphic","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Core framework dependency for model inheritance and ORM integration.","package":"Django","optional":false}],"imports":[{"symbol":"PolymorphicModel","correct":"from polymorphic.models import PolymorphicModel"},{"symbol":"PolymorphicParentModelAdmin","correct":"from polymorphic.admin import PolymorphicParentModelAdmin"},{"symbol":"PolymorphicChildModelAdmin","correct":"from polymorphic.admin import PolymorphicChildModelAdmin"},{"symbol":"PolymorphicManager","correct":"from polymorphic.managers import PolymorphicManager"},{"note":"The `drf-polymorphic` package was merged into `django-polymorphic` in v4.10.0. Update import paths accordingly.","wrong":"from rest_polymorphic.serializers import PolymorphicSerializer","symbol":"PolymorphicSerializer","correct":"from polymorphic.contrib.rest_framework.serializers import PolymorphicSerializer"}],"quickstart":{"code":"import os\nimport django\nfrom django.conf import settings\nfrom django.db import models\n\n# Minimal Django setup for runnable example\nsettings.configure(\n    INSTALLED_APPS=[\n        'django.contrib.auth',\n        'django.contrib.contenttypes',\n        'polymorphic',\n        __name__ # For models to be registered\n    ],\n    DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}}\n)\ndjango.setup()\n\nfrom polymorphic.models import PolymorphicModel\n\n# Define your polymorphic models\nclass Project(PolymorphicModel):\n    topic = models.CharField(max_length=90)\n\n    def __str__(self):\n        return f\"{self.__class__.__name__}: {self.topic}\"\n\nclass ArtProject(Project):\n    artist = models.CharField(max_length=90)\n\n    def __str__(self):\n        return f\"{self.__class__.__name__}: {self.topic} by {self.artist}\"\n\nclass ResearchProject(Project):\n    supervisor = models.CharField(max_length=90)\n\n    def __str__(self):\n        return f\"{self.__class__.__name__}: {self.topic} supervised by {self.supervisor}\"\n\n# Create database schema\nfrom django.core.management import call_command\ncall_command('makemigrations', __name__, interactive=False)\ncall_command('migrate', interactive=False)\n\n# Create objects\nProject.objects.create(topic=\"Department Party\")\nArtProject.objects.create(topic=\"Painting with Tim\", artist=\"T. Turner\")\nResearchProject.objects.create(topic=\"Swallow Aerodynamics\", supervisor=\"Dr. Winter\")\n\n# Query the base model to get polymorphic results\nall_projects = Project.objects.all()\nprint(\"All Projects:\")\nfor project in all_projects:\n    print(project)\n\n# Filter by subclass type\nart_projects = Project.objects.instance_of(ArtProject)\nprint(\"\\nArt Projects:\")\nfor project in art_projects:\n    print(project)\n","lang":"python","description":"This quickstart demonstrates how to define polymorphic models using `PolymorphicModel` and query them. It sets up a minimal Django environment, defines a base `Project` model and two child models (`ArtProject`, `ResearchProject`), creates instances, and then queries the base model to retrieve all objects as their most specific subclass types. It also shows how to filter by `instance_of()` a specific child type. Remember to add 'polymorphic' and 'django.contrib.contenttypes' to `INSTALLED_APPS`."},"warnings":[{"fix":"Be mindful of complex inheritance hierarchies. For large querysets with many distinct subclasses, consider optimizing queries if performance bottlenecks occur. Use `iterator(chunk_size=...)` to balance memory vs. DB round trips.","message":"Query performance can degrade with many distinct subclasses. Each unique subclass in a queryset requires an additional `INNER JOIN` query to fetch its specific fields, leading to `1 + N` queries (where N is the number of distinct subclasses) for a single `all()` call. While better than `N` queries, it's a consideration for very complex hierarchies.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Update your import paths from `rest_polymorphic.serializers` to `polymorphic.contrib.rest_framework.serializers`.","message":"The `drf-polymorphic` package was merged directly into `django-polymorphic` starting with version 4.10.0. This means import paths for `PolymorphicSerializer` and related components have changed.","severity":"breaking","affected_versions":">=4.10.0"},{"fix":"If polymorphic behavior is needed, avoid `values()` and `values_list()` and instead fetch full model instances. If you specifically need non-polymorphic behavior or a fixed set of fields, use `Model.base_objects.values(...)` which is guaranteed not to change.","message":"Methods like `values()` and `values_list()` do not return polymorphic results. They will return fields only from the base model, or specific fields if explicitly requested, but will not perform downcasting to subclasses.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Always use `python manage.py dumpdata --natural-primary --natural-foreign ...` for polymorphic models.","message":"When using `dumpdata` with polymorphic models, you must include the `--natural-primary` and `--natural-foreign` flags. Polymorphic models rely on Django's `ContentType` framework, and these flags ensure correct serialization and deserialization across different database instances.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Use the `.non_polymorphic()` queryset method instead, e.g., `ModelA.objects.non_polymorphic().all()`.","message":"The keyword argument `polymorphic=False` for disabling polymorphic behavior in queries is no longer supported.","severity":"deprecated","affected_versions":"Versions >=4.0.0 (exact version where removed is not explicitly stated in latest docs, but `.non_polymorphic()` is the replacement for recent versions)"},{"fix":"Replace `form = ...` with `base_form = ...` and `fieldsets = ...` with `base_fieldsets = ...` in `PolymorphicChildModelAdmin` definitions.","message":"In admin integration, when defining a `PolymorphicChildModelAdmin` that might be extended by further derived classes, use `base_form` and `base_fieldsets` attributes instead of the standard `form` and `fieldsets`. This ensures that additional fields from further child models are automatically added correctly.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-11T00:00:00.000Z","next_check":"2026-07-10T00:00:00.000Z"}