Fix errors raised with resolve_model_string

It now raises `ValueError` for a badly formatted string, and `NameError`
if it can not find the model. Error messages are not translated. Edit
handlers now use the function.
This commit is contained in:
Tim Heap 2014-08-22 10:06:09 +10:00
parent 999b052fe5
commit 7921abe924
3 changed files with 28 additions and 31 deletions

View file

@ -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')

View file

@ -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

View file

@ -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)