diff --git a/wagtail/wagtailadmin/edit_handlers.py b/wagtail/wagtailadmin/edit_handlers.py index 3e463523d..1c5ec6a09 100644 --- a/wagtail/wagtailadmin/edit_handlers.py +++ b/wagtail/wagtailadmin/edit_handlers.py @@ -19,8 +19,8 @@ from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy from wagtail.wagtailcore.models import Page -from wagtail.wagtailcore.utils import camelcase_to_underscore from wagtail.wagtailcore.fields import RichTextArea +from wagtail.wagtailcore.utils import camelcase_to_underscore, resolve_model_string FORM_FIELD_OVERRIDES = {} @@ -483,25 +483,16 @@ class BasePageChooserPanel(BaseChooserPanel): def target_content_type(cls): if cls._target_content_type is None: if cls.page_type: - if isinstance(cls.page_type, string_types): - # translate the passed model name into an actual model class - from django.db.models import get_model - try: - app_label, model_name = cls.page_type.split('.') - except ValueError: - raise ImproperlyConfigured("The page_type passed to PageChooserPanel must be of the form 'app_label.model_name'") + try: + model = resolve_model_string(cls.page_type) + except NameError: + raise ImproperlyConfigured("{0}.page_type must be of the form 'app_label.model_name', given {1!r}".format( + cls.__name__, cls.page_type)) + except ValueError: + raise ImproperlyConfigured("{0}.page_type refers to model {1!r} that has not been installed".format( + cls.__name__, cls.page_type)) - try: - page_type = get_model(app_label, model_name) - except LookupError: - page_type = None - - if page_type is None: - raise ImproperlyConfigured("PageChooserPanel refers to model '%s' that has not been installed" % cls.page_type) - else: - page_type = cls.page_type - - cls._target_content_type = ContentType.objects.get_for_model(page_type) + cls._target_content_type = ContentType.objects.get_for_model(model) else: # TODO: infer the content type by introspection on the foreign key cls._target_content_type = ContentType.objects.get_by_natural_key('wagtailcore', 'page') diff --git a/wagtail/wagtailcore/models.py b/wagtail/wagtailcore/models.py index 1fa436014..6b13c61de 100644 --- a/wagtail/wagtailcore/models.py +++ b/wagtail/wagtailcore/models.py @@ -20,7 +20,7 @@ from django.conf import settings from django.template.response import TemplateResponse from django.utils import timezone from django.utils.translation import ugettext_lazy as _ -from django.core.exceptions import ValidationError +from django.core.exceptions import ValidationError, ImproperlyConfigured from django.utils.functional import cached_property from django.utils.encoding import python_2_unicode_compatible @@ -517,8 +517,9 @@ class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, index.Indexed try: models = [resolve_model_string(model_string, cls._meta.app_label) for model_string in subpage_types] - except (NameError,) as err: - raise NameError(err.args[0] + ' (used in subpage_types') + except NameError as err: + raise ImproperlyConfigured("{0}.subpage_types must be a list of 'app_label.model_name' strings, given {1!r}".format( + cls.__name__, err.args[1])) res = list(map(ContentType.objects.get_for_model, models)) cls._clean_subpage_types = res @@ -541,7 +542,8 @@ class Page(six.with_metaclass(PageBase, MP_Node, ClusterableModel, index.Indexed models = [resolve_model_string(model_string, cls._meta.app_label) for model_string in parent_page_types] except NameError as err: - raise NameError(err.args[0] + ' (used in parent_page_types)') + raise ImproperlyConfigured("{0}.parent_page_types must be a list of 'app_label.model_name' strings, given {1!r}".format( + cls.__name__, err.args[1])) res = list(map(ContentType.objects.get_for_model, models)) cls._clean_parent_page_types = res diff --git a/wagtail/wagtailcore/utils.py b/wagtail/wagtailcore/utils.py index 52913beda..d03d5ae75 100644 --- a/wagtail/wagtailcore/utils.py +++ b/wagtail/wagtailcore/utils.py @@ -1,6 +1,5 @@ import re from django.db.models import Model, get_model -from django.utils.translation import ugettext_lazy as _ from six import string_types @@ -9,7 +8,7 @@ def camelcase_to_underscore(str): return re.sub('(((?<=[a-z])[A-Z])|([A-Z](?![A-Z]|$)))', '_\\1', str).lower().strip('_') -def resolve_model_string(model_string, default_app): +def resolve_model_string(model_string, default_app=None): """ Resolve an 'app_label.model_name' string in to an actual model class. If a model class is passed in, just return that. @@ -18,17 +17,22 @@ def resolve_model_string(model_string, default_app): try: app_label, model_name = model_string.split(".") except ValueError: - # If we can't split, assume a model in current app - app_label = default_app - model_name = model_string + if default_app is not None: + # If we can't split, assume a model in current app + app_label = default_app + model_name = model_string + else: + raise ValueError("Can not resolve {0!r} in to a model. Model names " + "should be in the form app_label.model_name".format( + model_string), model_string) model = get_model(app_label, model_name) if not model: - raise NameError(_("name '{0}' is not defined.").format(model_string)) + raise NameError("Can not resolve {0!r} in to a model".format(model_string), model_string) return model - elif issubclass(model_string, Model): + elif model_string is not None and issubclass(model_string, Model): return model else: - raise ValueError(_("Can not resolve '{0!r}' in to a model").format(model_string)) + raise NameError("Can not resolve {0!r} in to a model".format(model_string), model_string)