### Install Project Dependencies Source: https://github.com/django-commons/django-polymorphic/blob/main/CONTRIBUTING.md Installs development dependencies if uv and Python are already set up. ```bash just install ``` -------------------------------- ### Install Development Tools Source: https://github.com/django-commons/django-polymorphic/blob/main/CONTRIBUTING.md Installs the necessary build tooling using 'just'. Can optionally specify a Python version. ```bash just setup ``` ```bash just setup 3.12 ``` -------------------------------- ### Install django-polymorphic Source: https://github.com/django-commons/django-polymorphic/blob/main/README.md Use pip to install the django-polymorphic package. ```bash $ pip install django-polymorphic ``` -------------------------------- ### Live Documentation Server Source: https://github.com/django-commons/django-polymorphic/blob/main/CONTRIBUTING.md Starts a local server to view documentation with auto-rebuild capabilities. ```bash just docs-live ``` -------------------------------- ### Install Django Polymorphic Source: https://context7.com/django-commons/django-polymorphic/llms.txt Install the package using pip and add 'polymorphic' and 'django.contrib.contenttypes' to your INSTALLED_APPS in settings.py. ```python # Terminal # pip install django-polymorphic # settings.py INSTALLED_APPS = [ # ... 'polymorphic', 'django.contrib.contenttypes', ] ``` -------------------------------- ### Install Playwright for UI Tests Source: https://github.com/django-commons/django-polymorphic/blob/main/CONTRIBUTING.md Installs Playwright, a tool for end-to-end testing, which is required for running UI tests. ```bash just install-playwright ``` -------------------------------- ### Configure URL Patterns for Polymorphic Formset View Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/integrations/index.md Example of Django URL configuration to route requests to the ArticleFormSetView. This sets up the 'articles' URL path within the 'extra_views' app namespace. ```python from django.urls import path from .views import ArticleFormSetView app_name = "extra_views" urlpatterns = [ path("articles/", ArticleFormSetView.as_view(), name="articles"), ] ``` -------------------------------- ### Test GET Request Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/integrations/drf.md Use `httpie` to send a GET request to the API endpoint to retrieve polymorphic data. ```bash $ http GET "http://localhost:8000/projects/" ``` -------------------------------- ### Create Polymorphic Object with Custom Resource Type Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/integrations/drf.md Example of making a POST request to create a new polymorphic object using a custom resource type field name ('projecttype') and providing specific fields for the object. ```bash $ http POST "http://localhost:8000/projects/" projecttype="artproject" topic="Guernica" artist="Picasso" ``` -------------------------------- ### Django Polymorphic Migration Example Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/changelog/index.md This is an example of a migration that may be generated when updating polymorphic models. It is an expected side effect of fixing issue #815. ```python migrations.AlterModelOptions( name='modelname', options={}, ) ``` -------------------------------- ### Get Real Instances from Queryset Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/changelog/index.md Demonstrates the simplified usage of `.get_real_instances()` on a non-polymorphic queryset. This is equivalent to fetching all objects without the non-polymorphic filter. ```python qs = ModelA.objects.all().non_polymorphic() qs.get_real_instances() ``` -------------------------------- ### Type Hints for Polymorphic Managers and Relations Source: https://context7.com/django-commons/django-polymorphic/llms.txt Utilize `django-polymorphic`'s type hints for managers and relationship descriptors to improve static analysis with tools like mypy or pyright. This requires `django-stubs` to be installed. Annotate managers with `PolymorphicManager` and relationship fields with descriptors like `PolymorphicForwardManyToOneDescriptor`. ```python from __future__ import annotations import typing as t from typing_extensions import Self from django.db import models from polymorphic.models import PolymorphicModel from polymorphic.managers import ( PolymorphicManager, PolymorphicForwardManyToOneDescriptor, PolymorphicReverseManyToOneDescriptor, PolymorphicManyToManyDescriptor, Nullable, ) class ParentModel(PolymorphicModel): objects: t.ClassVar[ PolymorphicManager[ Self | Child1 | Child2, # union of all polymorphic types Self, # base type returned by non_polymorphic() ] ] = PolymorphicManager() class Child1(ParentModel): pass class Child2(Child1): pass class RelatedModel(models.Model): # Typed nullable ForeignKey to a polymorphic model parent: PolymorphicForwardManyToOneDescriptor[ ParentModel | Child1 | Child2, ParentModel, Nullable, # omit if not null=True ] = models.ForeignKey( # type: ignore[assignment] ParentModel, on_delete=models.CASCADE, null=True ) # Typed reverse FK relation parents_back: PolymorphicReverseManyToOneDescriptor[ ParentModel | Child1 | Child2, ParentModel, ] # Typed ManyToMany (forward or reverse) poly_items: PolymorphicManyToManyDescriptor[ ParentModel | Child1 | Child2, ParentModel, ] = models.ManyToManyField("ParentModel") # type: ignore[assignment] # Inferred types: # ParentModel.objects.all() → PolymorphicQuerySet[ParentModel | Child1 | Child2] # ParentModel.objects.instance_of(Child1) → PolymorphicQuerySet[Child1] # Child1.objects.non_polymorphic() → QuerySet[Child1] # RelatedModel().parent → ParentModel | Child1 | Child2 | None ``` -------------------------------- ### Register Polymorphic Models in Django Admin Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/admin.md Example demonstrating how to register parent and child polymorphic models using PolymorphicParentModelAdmin and PolymorphicChildModelAdmin. Child models can be explicitly set to show in the admin index. ```python from django.contrib import admin from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, PolymorphicChildModelFilter from .models import ModelA, ModelB, ModelC, StandardModel class ModelAChildAdmin(PolymorphicChildModelAdmin): """ Base admin class for all child models """ base_model = ModelA # Optional, explicitly set here. # By using these `base_...` attributes instead of the regular ModelAdmin `form` and `fieldsets`, # the additional fields of the child models are automatically added to the admin form. base_form = ... base_fieldsets = ( ... ) @admin.register(ModelB) class ModelBAdmin(ModelAChildAdmin): base_model = ModelB # Explicitly set here! # define custom features here @admin.register(ModelC) class ModelCAdmin(ModelBAdmin): base_model = ModelC # Explicitly set here! show_in_index = True # makes child model admin visible in main admin site # define custom features here @admin.register(ModelA) class ModelAParentAdmin(PolymorphicParentModelAdmin): """ The parent model admin """ base_model = ModelA # Optional, explicitly set here. child_models = (ModelB, ModelC) list_filter = (PolymorphicChildModelFilter,) # This is optional. ``` -------------------------------- ### Set Global Default Batch Size for Polymorphic Querysets Source: https://context7.com/django-commons/django-polymorphic/llms.txt Tune memory versus round-trip trade-offs by setting the global default batch size for polymorphic querysets. This can be done at application startup, for example, in your AppConfig.ready() method. ```python from polymorphic import query # Change the global default batch size at startup (e.g., in AppConfig.ready()) query.Polymorphic_QuerySet_objects_per_request = 5000 ``` -------------------------------- ### Define Polymorphic Model Hierarchy Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/integrations/index.md Example of a polymorphic model hierarchy using Article as the base class with BlogPost and NewsArticle as subclasses. This setup is used for integration examples. ```python from django.db import models from polymorphic.models import PolymorphicModel class Article(PolymorphicModel): title = models.CharField(max_length=100) content = models.TextField() created = models.DateTimeField(auto_now_add=True) def __str__(self): return self.title class BlogPost(Article): author = models.CharField(max_length=100) class NewsArticle(Article): source = models.CharField(max_length=100) ``` -------------------------------- ### Get Real Instances from Base Objects Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/changelog/index.md Converts a queryset or list of base objects into a list of their real polymorphic instances. Useful when starting with a queryset that might have been filtered or modified in a non-polymorphic way. ```python real_objects = ModelA.objects.get_real_instances(base_objects_list_or_queryset) ``` -------------------------------- ### Build and Check Documentation Source: https://github.com/django-commons/django-polymorphic/blob/main/CONTRIBUTING.md Commands to build, lint, and check links for the project documentation. ```bash just docs ``` ```bash just check-docs ``` ```bash just check-docs-links ``` -------------------------------- ### Run Unit Tests Source: https://github.com/django-commons/django-polymorphic/blob/main/CONTRIBUTING.md Commands to execute the full test suite or specific tests by path, class, or function. ```bash just test ``` ```bash just test ::ClassName::FunctionName ``` ```bash just test src/polymorphic/tests/test_admin.py ``` ```bash just test src/polymorphic/tests/test_admin.py::PolymorphicAdminTests::test_admin_registration ``` -------------------------------- ### Test POST Request Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/integrations/drf.md Use `httpie` to send a POST request to create a new polymorphic instance, specifying the `resourcetype`. ```bash $ http POST "http://localhost:8000/projects/" resourcetype="ArtProject" topic="Guernica" artist="Picasso" ``` -------------------------------- ### polymorphic.utils.prepare_for_copy Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/api/polymorphic.utils.md Prepares a model instance for copying by resetting primary keys and parent table pointers. This function is intended to be used before saving a new instance that is a copy of an existing one. It does not handle deep copying of related objects. ```APIDOC ## polymorphic.utils.prepare_for_copy(obj) ### Description Prepare a model instance for copying by resetting all primary keys and parent table pointers in the inheritance chain. **Copy semantics are application specific.** This function only resets the fields required to create a new instance when saved, it does not deep copy related objects or save the new instance (See [copying discussion in the Django documentation.](https://docs.djangoproject.com/en/stable/topics/db/queries/#copying-model-instances)): ```python from polymorphic.utils import prepare_for_copy original = YourModel.objects.get(pk=1) prepare_for_copy(original) # update any related fields here as needed original.save() # creates a new object in the database ``` **This function also works for non-polymorphic multi-table models.** ### Parameters **obj** (Model) – The model instance to prepare for copying. ### Return type None ``` -------------------------------- ### Create Polymorphic Objects Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/quickstart.md Create instances of your polymorphic models. ```python >>> 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 Non-Polymorphic Queryset Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/changelog/index.md Use `.non_polymorphic()` to obtain a queryset that behaves non-polymorphically. This is preferred over `.base_objects` as it only affects the queryset's polymorphic behavior. ```python ModelA.objects.non_polymorphic().extra(...) ``` -------------------------------- ### ManyToMany and ForeignKey to Polymorphic Models Source: https://context7.com/django-commons/django-polymorphic/llms.txt Relationship fields pointing to polymorphic models automatically return correctly-typed instances without extra configuration. This example demonstrates a ManyToMany relationship. ```python from django.db import models 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) class Portfolio(models.Model): # ManyToMany to a polymorphic model — works seamlessly projects = models.ManyToManyField(Project) portfolio = Portfolio.objects.create() portfolio.projects.add(Project.objects.get(id=1)) portfolio.projects.add(ArtProject.objects.get(id=2)) portfolio.projects.add(ResearchProject.objects.get(id=3)) portfolio.projects.all() # [ , , ] ``` -------------------------------- ### Configure INSTALLED_APPS for django-polymorphic Source: https://github.com/django-commons/django-polymorphic/blob/main/README.md Add 'polymorphic' and 'django.contrib.contenttypes' to your Django project's INSTALLED_APPS setting. The contenttypes framework is a dependency. ```python INSTALLED_APPS = [ ... "django.contrib.contenttypes", # we rely on the contenttypes framework "polymorphic" ] ``` -------------------------------- ### Running Tests with Django 1.3 Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/changelog/index.md For Django 1.3, the command to run the polymorphic test suite has changed. Use 'python manage.py test polymorphic'. ```bash python manage.py test polymorphic ``` -------------------------------- ### Override Resource Type Determination Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/integrations/drf.md Override the `to_resource_type` method to customize how the resource type is determined from a model instance. This example converts the model's object name to lowercase. ```python class ProjectPolymorphicSerializer(PolymorphicSerializer): ... def to_resource_type(self, model_or_instance): return model_or_instance._meta.object_name.lower() ``` -------------------------------- ### Promote Parent Instance to Subclass with create_from_super() Source: https://context7.com/django-commons/django-polymorphic/llms.txt Creates a subclass instance from an existing parent instance, effectively 'promoting' the object down the inheritance chain. The parent must be a direct parent of the target subclass. This is useful for converting a generic parent object into a more specific child type. ```python from myapp.models import ModelA, ModelB # Existing parent instance parent = ModelA.objects.get(id=1) # # Promote to ModelB (direct child of ModelA), providing ModelB-specific fields child = ModelB.objects.create_from_super(parent, field2='new_value') # child is now # For multi-level promotion, call repeatedly from myapp.models import ModelC grandchild = ModelC.objects.create_from_super(child, field3='another_value') ``` -------------------------------- ### Get Model Name Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/api/polymorphic.templatetags/polymorphic_formset_tags.md This template tag returns the string representation of a model's name, whether provided with a model class or an instance. It's helpful for displaying model information in templates. ```django {{ model|as_model_name }} ``` -------------------------------- ### Create Child Instance from Parent Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/advanced.md Use `create_from_super()` to instantiate a subclass from a superclass instance. Ensure the super instance is a direct superclass and provide all required fields for the subclass. ```python super_instance = ModelA.objects.get(id=1) sub_instance = ModelB.objects.create_from_super(super_instance, field2='value2') ``` -------------------------------- ### URL Configuration for Views Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/views.md Defines the URL patterns for the project type selection and creation views. Uses Django's path converters and view names for routing. ```python from django.urls import path from .views import ProjectTypeSelectView, ProjectCreateView urlpatterns = [ path("select/", ProjectTypeSelectView.as_view(), name="project-select"), path("create/", ProjectCreateView.as_view(), name="project-create"), ] ``` -------------------------------- ### Get Form Type Name Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/api/polymorphic.templatetags/polymorphic_formset_tags.md Use this template tag to retrieve the model name for a given form instance. This is useful for dynamically setting attributes or classes based on the form's underlying model type. ```django {{ form|as_form_type }} ``` -------------------------------- ### Prepare Model Instance for Copying Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/api/polymorphic.utils.md Use this function to reset primary keys and parent table pointers before copying a model instance. It prepares the instance for saving as a new object. This also works for non-polymorphic multi-table models. ```python from polymorphic.utils import prepare_for_copy original = YourModel.objects.get(pk=1) prepare_for_copy(original) # update any related fields here as needed original.save() # creates a new object in the database ``` -------------------------------- ### prepare_for_copy() utility Source: https://context7.com/django-commons/django-polymorphic/llms.txt Use prepare_for_copy to reset primary key and parent pointer fields on a model instance, preparing it to be saved as a new copy. This function works correctly across all levels of multi-table inheritance. ```python from polymorphic.utils import prepare_for_copy from myapp.models import ArtProject original = ArtProject.objects.get(id=2) # prepare_for_copy(original) original.save() # original is now a new copy with a new primary key print(original.pk) # e.g., 4 — a new row ``` -------------------------------- ### Create a Polymorphic Formset View with django-extra-views Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/integrations/index.md Example of a Django view using PolymorphicFormSetView to handle polymorphic formsets. It defines the base model, template, success URL, and specifies formset children for different polymorphic types. ```python from polymorphic.contrib.extra_views import PolymorphicFormSetView from polymorphic.formsets import PolymorphicFormSetChild from django.urls import reverse_lazy from ..models import Article, BlogPost, NewsArticle class ArticleFormSetView(PolymorphicFormSetView): model = Article template_name = "extra_views/article_formset.html" success_url = reverse_lazy("extra_views:articles") fields = "__all__" # extra will add two empty forms for models in the order of their appearance # in formset_children factory_kwargs = {"extra": 2, "can_delete": True} formset_children = [ PolymorphicFormSetChild(BlogPost, fields="__all__"), PolymorphicFormSetChild(NewsArticle, fields="__all__"), ] ``` -------------------------------- ### defer Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/api/polymorphic.managers.md Translates field paths and calls the vanilla defer method. Retains a copy of original fields for later use. ```APIDOC ## defer(*fields: str) ### Description Translates the field paths in the args, then calls vanilla defer. Also retains a copy of the original fields passed, which will be needed when retrieving the real instance. ### Parameters * **fields** (str) - Required - The fields to defer. ### Return type Self ``` -------------------------------- ### Project Creation Form View Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/views.md A CreateView that dynamically determines the form class based on a 'model' query parameter. This allows for creating specific polymorphic model types. ```python class ProjectCreateView(CreateView): model = Project template_name = "project_form.html" def get_success_url(self): return reverse("project-select") def get_form_class(self): # Get the requested model label from query parameter model_label = self.request.GET.get("model") if not model_label: # Fallback or redirect to selection view return super().get_form_class() # Get the model class using the app registry model_class = apps.get_model(model_label) # Create a form for this model # You can also use a factory or a dict mapping if you have custom forms class SpecificForm(forms.ModelForm): class Meta: model = model_class fields = "__all__" # Or specify fields return SpecificForm def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) # Pass the model label to the template so it can be preserved # in the form action context["model_label"] = self.request.GET.get("model") return context ``` -------------------------------- ### Update Django Settings Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/quickstart.md Add 'polymorphic' and 'django.contrib.contenttypes' to your INSTALLED_APPS. ```python INSTALLED_APPS += ( 'polymorphic', 'django.contrib.contenttypes', ) ``` -------------------------------- ### Create a Release Tag Source: https://github.com/django-commons/django-polymorphic/blob/main/CONTRIBUTING.md Triggers the release workflow by creating a git tag with a specified version number. Requires git tag signing to be enabled. ```bash just release x.x.x ``` -------------------------------- ### ShowFieldBase Methods Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/api/index.md Base class for show field descriptors. ```APIDOC ## ShowFieldBase.__init__(*args, **kwargs) ### Description Initializes the ShowFieldBase. ### Method ``` ShowFieldBase.__init__(*args, **kwargs) ``` ### Parameters - **args**, **kwargs**: Initialization arguments. ### Response None. ``` -------------------------------- ### Type Checking Source: https://github.com/django-commons/django-polymorphic/blob/main/CONTRIBUTING.md Commands to run static type checking using mypy and pyright. ```bash just check-types ``` ```bash just check-types-mypy ``` ```bash just check-types-pyright ``` -------------------------------- ### Project Form Template Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/views.md HTML template for the specific project form. It preserves the 'model' query parameter in the form's action attribute to maintain context. ```html
{% csrf_token %} {{ form.as_p }}
``` -------------------------------- ### create_from_super() Source: https://context7.com/django-commons/django-polymorphic/llms.txt Creates a subclass instance from an existing parent instance, effectively promoting the object down the inheritance chain. ```APIDOC ## create_from_super() ### Description Creates a subclass instance from an existing parent instance, effectively "promoting" the object down the inheritance chain. The parent must be a direct parent of the target subclass. ### Method Manager method ### Parameters - **parent_instance** (Model instance) - Required - The existing parent instance. - **kwargs** - Required - Fields specific to the subclass. ### Request Example ```python from myapp.models import ModelA, ModelB # Existing parent instance parent = ModelA.objects.get(id=1) # # Promote to ModelB (direct child of ModelA), providing ModelB-specific fields child = ModelB.objects.create_from_super(parent, field2='new_value') # child is now # For multi-level promotion, call repeatedly from myapp.models import ModelC grandchild = ModelC.objects.create_from_super(child, field3='another_value') ``` ### Response #### Success Response - **Model instance** - The newly created subclass instance. ``` -------------------------------- ### ShowFieldContent Methods Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/api/index.md Descriptor for showing field content. ```APIDOC ## ShowFieldContent.__init__(*args, **kwargs) ### Description Initializes the ShowFieldContent descriptor. ### Method ``` ShowFieldContent.__init__(*args, **kwargs) ``` ### Parameters - **args**, **kwargs**: Initialization arguments. ### Response None. ``` -------------------------------- ### Typing Polymorphic Foreign Keys Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/typing.md Use `PolymorphicForwardManyToOneDescriptor` and `PolymorphicReverseManyToOneDescriptor` to provide type hints for foreign key relationships. This helps static analysis tools understand the types involved in forward and reverse relationships. ```python from django.db import models from polymorphic.models import PolymorphicModel from polymorphic.managers import ( PolymorphicForwardManyToOneDescriptor, PolymorphicReverseManyToOneDescriptor, Nullable, # Alias for typing.Literal[True] ) class ParentModel(PolymorphicModel): related_forward = models.ForeignKey( "RelatedModel", on_delete=models.CASCADE, related_name="parents_reverse" ) class Child1(ParentModel): pass class Child2(Child1): pass class RelatedModel(models.Model): # fmt: off # Foreign Key Descriptor Type Hint: # 1. Class Attribute: ForwardManyToOneDescriptor # 2. Instance attribute: Union of all listed model types or None parent: PolymorphicForwardManyToOneDescriptor[ ParentModel | Child1 | Child2, # all possible polymorphic types ParentModel, # the base type (for non_polymorphic) Nullable, # when null=True ] = models.ForeignKey( ParentModel, on_delete=models.CASCADE, null=True, ) # type: ignore[assignment] # Reverse FK Relation Descriptor Type Hint: # 1. Class Attribute: ReverseManyToOneDescriptor # 2. Instance attribute: Union of all listed model types parents_reverse: PolymorphicReverseManyToOneDescriptor[ ParentModel | Child1 | Child2, # all possible polymorphic types ParentModel, # the base type (for non_polymorphic) # nullable defaults to False ] # fmt: on ``` ```python RelatedModel().parent: Optional[ParentModel | Child1 | Child2] RelatedModel().children.all(): PolymorphicQuerySet[ParentModel | Child1 | Child2] ``` -------------------------------- ### Prepare Polymorphic Object for Copying Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/advanced.md Utilize the prepare_for_copy utility function to reset necessary fields on a polymorphic model instance, preparing it for duplication. After calling this function and saving, the object becomes a copy. ```python from polymorphic.utils import prepare_for_copy obj = ModelB.objects.first() prepare_for_copy(obj) obj.save() # obj is now a copy of the original ModelB instance ``` -------------------------------- ### Create ViewSet with Polymorphic Serializer Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/integrations/drf.md Configure a `ModelViewSet` to use the `ProjectPolymorphicSerializer` for handling polymorphic data. ```python from rest_framework import viewsets from .models import Project from .example_serializers import ProjectPolymorphicSerializer class ProjectViewSet(viewsets.ModelViewSet): queryset = Project.objects.all() serializer_class = ProjectPolymorphicSerializer ``` -------------------------------- ### Polymorphic Object Creation Views and Forms Source: https://context7.com/django-commons/django-polymorphic/llms.txt Use this pattern when a single URL needs to present different form fields for different subtypes. The `ProjectTypeSelectView` allows users to choose a project type, and `ProjectCreateView` dynamically generates a form based on that choice. ```python from django.apps import apps from django import forms from django.shortcuts import redirect from django.urls import reverse, path from django.views.generic import FormView, CreateView from myapp.models import Project, ArtProject, ResearchProject class ProjectTypeChoiceForm(forms.Form): model_type = forms.ChoiceField(widget=forms.RadioSelect) class ProjectTypeSelectView(FormView): form_class = ProjectTypeChoiceForm template_name = "project_type_select.html" def get_form(self, form_class=None): form = super().get_form(form_class) form.fields["model_type"].choices = [ (m._meta.label, m._meta.verbose_name) for m in [ArtProject, ResearchProject] ] return form def form_valid(self, form): label = form.cleaned_data["model_type"] return redirect(f"{reverse('project-create')}?model={label}") class ProjectCreateView(CreateView): model = Project template_name = "project_form.html" def get_success_url(self): return reverse("project-select") def get_form_class(self): label = self.request.GET.get("model") if not label: return super().get_form_class() model_class = apps.get_model(label) class SpecificForm(forms.ModelForm): class Meta: model = model_class fields = "__all__" return SpecificForm urlpatterns = [ path("select/", ProjectTypeSelectView.as_view(), name="project-select"), path("create/", ProjectCreateView.as_view(), name="project-create"), ] ``` -------------------------------- ### ShowFieldTypeAndContent Methods Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/api/index.md Descriptor for showing both field type and content. ```APIDOC ## ShowFieldTypeAndContent.__init__(*args, **kwargs) ### Description Initializes the ShowFieldTypeAndContent descriptor. ### Method ``` ShowFieldTypeAndContent.__init__(*args, **kwargs) ``` ### Parameters - **args**, **kwargs**: Initialization arguments. ### Response None. ``` -------------------------------- ### Type Hints for Typed Managers and Relationship Descriptors Source: https://context7.com/django-commons/django-polymorphic/llms.txt Provides type hints for managers and relationship fields in polymorphic models, enhancing static analysis with tools like mypy and pyright. Requires `django-stubs`. ```APIDOC ## Type Hints — Typed Managers and Relationship Descriptors Since v4.11, django-polymorphic ships full type hints. Annotate managers and relationship fields with the provided generic descriptor classes for accurate mypy/pyright inference. Requires `django-stubs` in the type-checking environment. ```python from __future__ import annotations import typing as t from typing_extensions import Self from django.db import models from polymorphic.models import PolymorphicModel from polymorphic.managers import ( PolymorphicManager, PolymorphicForwardManyToOneDescriptor, PolymorphicReverseManyToOneDescriptor, PolymorphicManyToManyDescriptor, Nullable, ) class ParentModel(PolymorphicModel): objects: t.ClassVar[ PolymorphicManager[ Self | Child1 | Child2, # union of all polymorphic types Self, # base type returned by non_polymorphic() ] ] = PolymorphicManager() class Child1(ParentModel): pass class Child2(Child1): pass class RelatedModel(models.Model): # Typed nullable ForeignKey to a polymorphic model parent: PolymorphicForwardManyToOneDescriptor[ ParentModel | Child1 | Child2, ParentModel, Nullable, # omit if not null=True ] = models.ForeignKey( # type: ignore[assignment] ParentModel, on_delete=models.CASCADE, null=True ) # Typed reverse FK relation parents_back: PolymorphicReverseManyToOneDescriptor[ ParentModel | Child1 | Child2, ParentModel, ] # Typed ManyToMany (forward or reverse) poly_items: PolymorphicManyToManyDescriptor[ ParentModel | Child1 | Child2, ParentModel, ] = models.ManyToManyField("ParentModel") # type: ignore[assignment] # Inferred types: # ParentModel.objects.all() → PolymorphicQuerySet[ParentModel | Child1 | Child2] # ParentModel.objects.instance_of(Child1) → PolymorphicQuerySet[Child1] # Child1.objects.non_polymorphic() → QuerySet[Child1] # RelatedModel().parent → ParentModel | Child1 | Child2 | None ``` ``` -------------------------------- ### Project Type Select Template Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/views.md HTML template for the project type selection form. It renders the form and includes a submit button. ```html
{% csrf_token %} {{ form.as_p }}
``` -------------------------------- ### Define Custom Polymorphic Queryset with as_manager Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/managers.md Alternatively, define a custom queryset inheriting from PolymorphicQuerySet and use its as_manager() shortcut to create a manager instance. This is a concise way to attach custom queryset logic to a model. ```python from polymorphic.models import PolymorphicModel from polymorphic.query import PolymorphicQuerySet class MyQuerySet(PolymorphicQuerySet): def my_queryset_method(self): ... class MyModel(PolymorphicModel): my_objects = MyQuerySet.as_manager() ... ``` -------------------------------- ### Define Custom Polymorphic Queryset with from_queryset Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/managers.md Create a custom queryset by inheriting from PolymorphicQuerySet and then use PolymorphicManager.from_queryset() to associate it with a manager. This allows custom queryset methods to be available through the manager. ```python from polymorphic.models import PolymorphicModel from polymorphic.managers import PolymorphicManager from polymorphic.query import PolymorphicQuerySet class MyQuerySet(PolymorphicQuerySet): def my_queryset_method(self): ... class MyModel(PolymorphicModel): my_objects = PolymorphicManager.from_queryset(MyQuerySet)() ... ``` -------------------------------- ### Format and Lint Code Source: https://github.com/django-commons/django-polymorphic/blob/main/CONTRIBUTING.md Commands to fix formatting and linting issues, and to run static analysis checks. ```bash just fix ``` ```bash just check ``` ```bash just format ``` -------------------------------- ### Debug UI Tests Source: https://github.com/django-commons/django-polymorphic/blob/main/CONTRIBUTING.md Runs UI tests with a debugger enabled, allowing step-through execution of UI actions in a browser. ```bash just debug-test -k ``` -------------------------------- ### Batch Resolve Base Objects to Subclasses with get_real_instances() Source: https://context7.com/django-commons/django-polymorphic/llms.txt Efficiently converts a queryset or list of base-model objects into their real subclass instances using a minimal number of SQL queries. Useful when dealing with collections of polymorphic objects. ```python from myapp.models import ModelA # From an existing queryset of base objects base_qs = ModelA.objects.non_polymorphic().filter(field1__startswith='A') real_objects = base_qs.get_real_instances() # From an arbitrary list of base instances base_list = list(ModelA.objects.non_polymorphic().all()) real_objects = ModelA.objects.get_real_instances(base_list) # Expected: [ , , ] print(real_objects) ``` -------------------------------- ### Vanilla Django Retrieval (for comparison) Source: https://github.com/django-commons/django-polymorphic/blob/main/README.md Illustrates the default behavior of Django's ORM when querying inherited models without django-polymorphic. Base class objects are returned, losing subclass-specific information. ```python >>> Project.objects.all() [ ] ``` -------------------------------- ### PolymorphicQuerySet.bulk_create Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/api/index.md Bulk creates objects in the database. ```APIDOC ## PolymorphicQuerySet.bulk_create() ### Description Efficiently creates multiple objects in the database in a single SQL query. This method is optimized for performance when inserting many records. ### Parameters - `objs` (list): A list of model instances to create. - `batch_size` (int, optional): The number of objects to insert per batch. - `ignore_conflicts` (bool, optional): If True, ignore unique constraint violations. - `update_conflicts` (list, optional): Fields to update if a conflict occurs. - `update_fields` (list, optional): Fields to update if `update_conflicts` is used. - `exclude` (list, optional): Fields to exclude from the update if `update_conflicts` is used. ### Returns - A list of the created objects. ### Example ```python from myapp.models import MyModel objects_to_create = [MyModel(field1='value1'), MyModel(field1='value2')] created_objects = MyModel.objects.bulk_create(objects_to_create) ``` ``` -------------------------------- ### PolymorphicFormset Constructor Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/api/polymorphic.formsets.md The `__init__` method of the PolymorphicFormset class allows for customization when creating a formset for polymorphic models. ```APIDOC ## PolymorphicFormset(\*args, \*\*kwargs) ### Description Initializes a formset for polymorphic models, allowing for customization of the form, fields, and other formset-related options. ### Parameters #### Arguments - **model** (type[models.Model]) - The model class to create the formset for. - **form** (type[ModelForm[Any]]) - The form class to use for each form in the formset. Defaults to `django.forms.ModelForm`. - **fields** (list[str] | None) - A list of fields to include in the formset. - **exclude** (tuple[str, ...] | list[str] | None) - A list or tuple of fields to exclude from the formset. - **formfield_callback** (Callable[..., Any] | None) - A callback function to customize formfield creation. - **widgets** (dict[str, Any] | None) - A dictionary mapping field names to widget instances. - **localized_fields** (list[str] | None) - A list of fields that are localized. - **labels** (dict[str, str] | None) - A dictionary mapping field names to labels. - **help_texts** (dict[str, str] | None) - A dictionary mapping field names to help texts. - **error_messages** (dict[str, dict[str, str]] | None) - A dictionary mapping field names to error messages. ``` -------------------------------- ### Enable Pretty Printing for Querysets Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/changelog/index.md To enable the old behavior of pretty printing for querysets, inherit from ShowFieldType instead of just PolymorphicModel. ```python >>> class Project(PolymorphicModel, ShowFieldType): ``` -------------------------------- ### Custom Manager with PolymorphicQuerySet Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/changelog/index.md Define a custom manager using `PolymorphicQuerySet.as_manager()` for model code. For manager code, use `PolymorphicManager.from_queryset()` to create a manager from a custom queryset. ```python # In model code: objects = PolymorphicQuerySet.as_manager() # For manager code: MyCustomManager = PolymorphicManager.from_queryset(MyCustomQuerySet) ``` -------------------------------- ### Django Admin Configuration with django-reversion Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/integrations/index.md Configure Django admin classes to support django-reversion with polymorphic models. Inherit from PolymorphicParentModelAdmin/PolymorphicChildModelAdmin and VersionAdmin. ```python from django.contrib import admin from polymorphic.admin import ( PolymorphicParentModelAdmin, PolymorphicChildModelAdmin, ) from reversion.admin import VersionAdmin from ..models import Article, BlogPost, NewsArticle class ArticleChildAdmin(PolymorphicChildModelAdmin, VersionAdmin): base_model = Article @admin.register(BlogPost) class BlogPostAdmin(ArticleChildAdmin): pass @admin.register(NewsArticle) class NewsArticleAdmin(ArticleChildAdmin): pass class ArticleParentAdmin(VersionAdmin, PolymorphicParentModelAdmin): """ Parent admin for Article model with reversion support. Note: VersionAdmin must come before PolymorphicParentModelAdmin in the inheritance order. """ base_model = Article child_models = (BlogPost, NewsArticle) list_display = ("title", "created") admin.site.register(Article, ArticleParentAdmin) ``` -------------------------------- ### Type Hinting for RelatedModel Instance Attributes Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/typing.md Illustrates the expected type hints for the 'parent_forward' and 'parent_reverse' attributes on an instance of RelatedModel, showing the union of possible polymorphic types and whether None is included. ```python RelatedModel().parent_forward: ParentModel | Child1 | Child2 | None RelatedModel().parent_reverse: ParentModel | Child1 | Child2 ``` -------------------------------- ### get_real_instances Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/api/polymorphic.managers.md Casts a list of objects to their actual classes more efficiently than a list comprehension. ```APIDOC ## get_real_instances(base_result_objects=None) ### Description Casts a list of objects to their actual classes. This is done more efficiently than a list comprehension. ### Parameters * **base_result_objects** (Iterable[_All] | None) - Optional - The iterable of base result objects to cast. ### Return type PolymorphicQuerySet ``` -------------------------------- ### Create and Retrieve Polymorphic Models Source: https://github.com/django-commons/django-polymorphic/blob/main/README.md Demonstrates creating instances of inherited models and then retrieving them via the base model. django-polymorphic ensures that the correct subclass instances are returned. ```python >>> 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") ``` ```python >>> Project.objects.all() [ ] ``` -------------------------------- ### Extend PolymorphicManager and PolymorphicQuerySet Source: https://context7.com/django-commons/django-polymorphic/llms.txt Demonstrates how to extend `PolymorphicManager` or `PolymorphicQuerySet` to add custom manager methods. These custom methods are automatically inherited by subclasses of the polymorphic model. ```python from django.db import models from polymorphic.models import PolymorphicModel from polymorphic.managers import PolymorphicManager from polymorphic.query import PolymorphicQuerySet # Option 1: Custom manager class class TimeOrderedManager(PolymorphicManager): def get_queryset(self): return super().get_queryset().order_by('-start_date') def most_recent(self): return self.get_queryset()[:10] class Project(PolymorphicModel): objects = PolymorphicManager() # default manager must come first objects_ordered = TimeOrderedManager() # custom manager start_date = models.DateTimeField() class ArtProject(Project): artist = models.CharField(max_length=30) # ArtProject inherits both managers ArtProject.objects_ordered.most_recent() # Option 2: Custom queryset as manager shortcut class MyQuerySet(PolymorphicQuerySet): def active(self): return self.filter(is_active=True) class MyModel(PolymorphicModel): is_active = models.BooleanField(default=True) my_objects = MyQuerySet.as_manager() MyModel.my_objects.active() ``` -------------------------------- ### ShowFieldContent Source: https://github.com/django-commons/django-polymorphic/blob/main/docs/api/polymorphic.showfields.md A model mixin that displays the object's class, its fields, and the content of those fields. ```APIDOC ## Class: ShowFieldContent ### Description Model mixin that shows the object's class, its fields, and field contents. Inherits from ShowFieldBase. ### Methods #### __init__() Initializes the ShowFieldContent instance. ```