From 5c0b561ba2fd6401435f6743b8f2f52273ae4316 Mon Sep 17 00:00:00 2001 From: Diederik van der Boor Date: Sun, 8 Oct 2017 21:53:12 +0200 Subject: [PATCH] Add UnsupportedChildType error for formsets This also replaces the PolymorphicInlineModelAdmin.get_get_child_inline_instance() and BasePolymorphicModelFormSet._construct_form() lookup with UnsupportedChildType (cherry picked from commit cafaf95f0650a38465711ab5bf7ff6f411c809e7) --- polymorphic/admin/inlines.py | 5 +++-- polymorphic/formsets/__init__.py | 2 ++ polymorphic/formsets/models.py | 22 ++++++++++++++++++++-- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/polymorphic/admin/inlines.py b/polymorphic/admin/inlines.py index deee7bb..bb25350 100644 --- a/polymorphic/admin/inlines.py +++ b/polymorphic/admin/inlines.py @@ -10,7 +10,8 @@ from django.contrib.admin.utils import flatten_fieldsets from django.core.exceptions import ImproperlyConfigured from django.forms import Media -from polymorphic.formsets import polymorphic_child_forms_factory, BasePolymorphicInlineFormSet, PolymorphicFormSetChild +from polymorphic.formsets import polymorphic_child_forms_factory, BasePolymorphicInlineFormSet, \ + PolymorphicFormSetChild, UnsupportedChildType from polymorphic.formsets.utils import add_media from .helpers import PolymorphicInlineSupportMixin @@ -89,7 +90,7 @@ class PolymorphicInlineModelAdmin(InlineModelAdmin): try: return self._child_inlines_lookup[model] except KeyError: - raise ValueError("Model '{0}' not found in child_inlines".format(model.__name__)) + raise UnsupportedChildType("Model '{0}' not found in child_inlines".format(model.__name__)) def get_formset(self, request, obj=None, **kwargs): """ diff --git a/polymorphic/formsets/__init__.py b/polymorphic/formsets/__init__.py index 02c47ae..1f3b335 100644 --- a/polymorphic/formsets/__init__.py +++ b/polymorphic/formsets/__init__.py @@ -12,6 +12,7 @@ from .models import ( BasePolymorphicModelFormSet, BasePolymorphicInlineFormSet, PolymorphicFormSetChild, + UnsupportedChildType, polymorphic_modelformset_factory, polymorphic_inlineformset_factory, polymorphic_child_forms_factory, @@ -27,6 +28,7 @@ __all__ = ( 'BasePolymorphicModelFormSet', 'BasePolymorphicInlineFormSet', 'PolymorphicFormSetChild', + 'UnsupportedChildType', 'polymorphic_modelformset_factory', 'polymorphic_inlineformset_factory', 'polymorphic_child_forms_factory', diff --git a/polymorphic/formsets/models.py b/polymorphic/formsets/models.py index b13adf8..9bac2b1 100644 --- a/polymorphic/formsets/models.py +++ b/polymorphic/formsets/models.py @@ -6,9 +6,16 @@ from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ImproperlyConfigured, ValidationError from django.forms.models import ModelForm, BaseModelFormSet, BaseInlineFormSet, modelform_factory, modelformset_factory, inlineformset_factory from django.utils.functional import cached_property + +from polymorphic.models import PolymorphicModel from .utils import add_media +class UnsupportedChildType(LookupError): + pass + + + class PolymorphicFormSetChild(object): """ Metadata to define the inline of a polymorphic child. @@ -168,7 +175,7 @@ class BasePolymorphicModelFormSet(BaseModelFormSet): model = ContentType.objects.get_for_id(ct_id).model_class() if model not in self.child_forms: # Perform basic validation, as we skip the ChoiceField here. - raise ValidationError("Child model type {0} is not part of the formset".format(model)) + raise UnsupportedChildType("Child model type {0} is not part of the formset".format(model)) else: if 'instance' in defaults: model = defaults['instance'].get_real_concrete_instance_class() # respect proxy models @@ -201,7 +208,18 @@ class BasePolymorphicModelFormSet(BaseModelFormSet): """ if not self.child_forms: raise ImproperlyConfigured("No 'child_forms' defined in {0}".format(self.__class__.__name__)) - return self.child_forms[model] + if not issubclass(model, PolymorphicModel): + raise TypeError("Expect polymorphic model type, not {0}".format(model)) + + try: + return self.child_forms[model] + except KeyError: + # This may happen when the query returns objects of a type that was not handled by the formset. + raise UnsupportedChildType( + "The '{0}' found a '{1}' model in the queryset, " + "but no form class is registered to display it.".format( + self.__class__.__name__, model.__name__ + )) def is_multipart(self): """