Browse Source

Fixed #9104 -- Moved FieldDoesNotExist to core.exceptions

Daniel Pyrathon 10 years ago
parent
commit
8958170755

+ 13 - 13
django/contrib/admin/checks.py

@@ -5,8 +5,8 @@ from itertools import chain
 
 from django.contrib.admin.utils import get_fields_from_path, NotRelationField, flatten
 from django.core import checks
+from django.core.exceptions import FieldDoesNotExist
 from django.db import models
-from django.db.models.fields import FieldDoesNotExist
 from django.forms.models import BaseModelForm, _get_foreign_key, BaseModelFormSet
 
 
@@ -53,7 +53,7 @@ class BaseModelAdminChecks(object):
 
         try:
             field = model._meta.get_field(field_name)
-        except models.FieldDoesNotExist:
+        except FieldDoesNotExist:
             return refer_to_missing_field(field=field_name, option=label,
                                           model=model, obj=cls, id='admin.E002')
         else:
@@ -168,7 +168,7 @@ class BaseModelAdminChecks(object):
         else:
             try:
                 field = model._meta.get_field(field_name)
-            except models.FieldDoesNotExist:
+            except FieldDoesNotExist:
                 # If we can't find a field on the model that matches, it could
                 # be an extra field on the form.
                 return []
@@ -248,7 +248,7 @@ class BaseModelAdminChecks(object):
 
         try:
             field = model._meta.get_field(field_name)
-        except models.FieldDoesNotExist:
+        except FieldDoesNotExist:
             return refer_to_missing_field(field=field_name, option=label,
                                           model=model, obj=cls, id='admin.E019')
         else:
@@ -277,7 +277,7 @@ class BaseModelAdminChecks(object):
 
         try:
             field = model._meta.get_field(field_name)
-        except models.FieldDoesNotExist:
+        except FieldDoesNotExist:
             return refer_to_missing_field(field=field_name, option=label,
                                           model=model, obj=cls, id='admin.E022')
         else:
@@ -357,7 +357,7 @@ class BaseModelAdminChecks(object):
 
         try:
             field = model._meta.get_field(field_name)
-        except models.FieldDoesNotExist:
+        except FieldDoesNotExist:
             return refer_to_missing_field(field=field_name, option=label,
                                           model=model, obj=cls, id='admin.E027')
         else:
@@ -394,7 +394,7 @@ class BaseModelAdminChecks(object):
 
         try:
             model._meta.get_field(field_name)
-        except models.FieldDoesNotExist:
+        except FieldDoesNotExist:
             return refer_to_missing_field(field=field_name, option=label,
                                           model=model, obj=cls, id='admin.E030')
         else:
@@ -439,7 +439,7 @@ class BaseModelAdminChecks(object):
 
             try:
                 model._meta.get_field(field_name)
-            except models.FieldDoesNotExist:
+            except FieldDoesNotExist:
                 return refer_to_missing_field(field=field_name, option=label,
                                               model=model, obj=cls, id='admin.E033')
             else:
@@ -468,7 +468,7 @@ class BaseModelAdminChecks(object):
         else:
             try:
                 model._meta.get_field(field_name)
-            except models.FieldDoesNotExist:
+            except FieldDoesNotExist:
                 return [
                     checks.Error(
                         "The value of '%s' is not a callable, an attribute of '%s', or an attribute of '%s.%s'." % (
@@ -581,7 +581,7 @@ class ModelAdminChecks(BaseModelAdminChecks):
             # getattr(model, item) could be an X_RelatedObjectsDescriptor
             try:
                 field = model._meta.get_field(item)
-            except models.FieldDoesNotExist:
+            except FieldDoesNotExist:
                 try:
                     field = getattr(model, item)
                 except AttributeError:
@@ -613,7 +613,7 @@ class ModelAdminChecks(BaseModelAdminChecks):
         else:
             try:
                 model._meta.get_field(item)
-            except models.FieldDoesNotExist:
+            except FieldDoesNotExist:
                 return [
                     # This is a deliberate repeat of E108; there's more than one path
                     # required to test this condition.
@@ -763,7 +763,7 @@ class ModelAdminChecks(BaseModelAdminChecks):
     def _check_list_editable_item(self, cls, model, field_name, label):
         try:
             field = model._meta.get_field_by_name(field_name)[0]
-        except models.FieldDoesNotExist:
+        except FieldDoesNotExist:
             return refer_to_missing_field(field=field_name, option=label,
                                           model=model, obj=cls, id='admin.E121')
         else:
@@ -833,7 +833,7 @@ class ModelAdminChecks(BaseModelAdminChecks):
         else:
             try:
                 field = model._meta.get_field(cls.date_hierarchy)
-            except models.FieldDoesNotExist:
+            except FieldDoesNotExist:
                 return refer_to_missing_field(option='date_hierarchy',
                                               field=cls.date_hierarchy,
                                               model=model, obj=cls, id='admin.E127')

+ 3 - 3
django/contrib/admin/options.py

@@ -20,12 +20,12 @@ from django.contrib.admin.templatetags.admin_urls import add_preserved_filters
 from django.contrib.auth import get_permission_codename
 from django.core import checks
 from django.core.exceptions import (PermissionDenied, ValidationError,
-    FieldError, ImproperlyConfigured)
+    FieldDoesNotExist, FieldError, ImproperlyConfigured)
 from django.core.paginator import Paginator
 from django.core.urlresolvers import reverse
 from django.db import models, transaction, router
 from django.db.models.constants import LOOKUP_SEP
-from django.db.models.fields import BLANK_CHOICE_DASH, FieldDoesNotExist
+from django.db.models.fields import BLANK_CHOICE_DASH
 from django.db.models.fields.related import ForeignObjectRel
 from django.db.models.sql.constants import QUERY_TERMS
 from django.forms.formsets import all_valid, DELETION_FIELD_NAME
@@ -1381,7 +1381,7 @@ class ModelAdmin(BaseModelAdmin):
         for k in initial:
             try:
                 f = self.model._meta.get_field(k)
-            except models.FieldDoesNotExist:
+            except FieldDoesNotExist:
                 continue
             # We have to special-case M2Ms as a list of comma-separated PKs.
             if isinstance(f, models.ManyToManyField):

+ 4 - 3
django/contrib/admin/utils.py

@@ -5,6 +5,7 @@ import datetime
 import decimal
 
 from django.contrib.auth import get_permission_codename
+from django.core.exceptions import FieldDoesNotExist
 from django.db import models
 from django.db.models.constants import LOOKUP_SEP
 from django.db.models.deletion import Collector
@@ -265,7 +266,7 @@ def lookup_field(name, obj, model_admin=None):
     opts = obj._meta
     try:
         f = opts.get_field(name)
-    except models.FieldDoesNotExist:
+    except FieldDoesNotExist:
         # For non-field values, the value is either a method, property or
         # returned via a callable.
         if callable(name):
@@ -306,7 +307,7 @@ def label_for_field(name, model, model_admin=None, return_attr=False):
         except AttributeError:
             # field is likely a ForeignObjectRel
             label = field.opts.verbose_name
-    except models.FieldDoesNotExist:
+    except FieldDoesNotExist:
         if name == "__unicode__":
             label = force_text(model._meta.verbose_name)
             attr = six.text_type
@@ -349,7 +350,7 @@ def help_text_for_field(name, model):
     help_text = ""
     try:
         field_data = model._meta.get_field_by_name(name)
-    except models.FieldDoesNotExist:
+    except FieldDoesNotExist:
         pass
     else:
         field = field_data[0]

+ 7 - 8
django/contrib/admin/validation.py

@@ -1,6 +1,5 @@
-from django.core.exceptions import ImproperlyConfigured
+from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured
 from django.db import models
-from django.db.models.fields import FieldDoesNotExist
 from django.forms.models import BaseModelForm, BaseModelFormSet, _get_foreign_key
 from django.contrib.admin.utils import get_fields_from_path, NotRelationField
 
@@ -42,7 +41,7 @@ class BaseValidator(object):
                     continue
                 try:
                     f = model._meta.get_field(field)
-                except models.FieldDoesNotExist:
+                except FieldDoesNotExist:
                     # If we can't find a field on the model that matches, it could be an
                     # extra field on the form; nothing to check so move on to the next field.
                     continue
@@ -196,7 +195,7 @@ class BaseValidator(object):
                         if not hasattr(model, field):
                             try:
                                 model._meta.get_field(field)
-                            except models.FieldDoesNotExist:
+                            except FieldDoesNotExist:
                                 raise ImproperlyConfigured(
                                     "%s.readonly_fields[%d], %r is not a callable or "
                                     "an attribute of %r or found in the model %r."
@@ -250,7 +249,7 @@ class ModelAdminValidator(BaseValidator):
                         if not hasattr(model, field):
                             try:
                                 model._meta.get_field(field)
-                            except models.FieldDoesNotExist:
+                            except FieldDoesNotExist:
                                 raise ImproperlyConfigured(
                                     "%s.list_display[%d], %r is not a callable or "
                                     "an attribute of %r or found in the model %r."
@@ -348,7 +347,7 @@ class ModelAdminValidator(BaseValidator):
             for idx, field_name in enumerate(cls.list_editable):
                 try:
                     field = model._meta.get_field_by_name(field_name)[0]
-                except models.FieldDoesNotExist:
+                except FieldDoesNotExist:
                     raise ImproperlyConfigured("'%s.list_editable[%d]' refers to a "
                         "field, '%s', not defined on %s.%s."
                         % (cls.__name__, idx, field_name, model._meta.app_label, model.__name__))
@@ -429,7 +428,7 @@ def check_isdict(cls, label, obj):
 def get_field(cls, model, label, field):
     try:
         return model._meta.get_field(field)
-    except models.FieldDoesNotExist:
+    except FieldDoesNotExist:
         raise ImproperlyConfigured("'%s.%s' refers to field '%s' that is missing from model '%s.%s'."
                 % (cls.__name__, label, field, model._meta.app_label, model.__name__))
 
@@ -437,7 +436,7 @@ def get_field(cls, model, label, field):
 def fetch_attr(cls, model, label, field):
     try:
         return model._meta.get_field(field)
-    except models.FieldDoesNotExist:
+    except FieldDoesNotExist:
         pass
     try:
         return getattr(model, field)

+ 3 - 4
django/contrib/admin/views/main.py

@@ -1,11 +1,10 @@
 from collections import OrderedDict
 import sys
 
-from django.core.exceptions import SuspiciousOperation, ImproperlyConfigured
+from django.core.exceptions import FieldDoesNotExist, SuspiciousOperation, ImproperlyConfigured
 from django.core.paginator import InvalidPage
 from django.core.urlresolvers import reverse
 from django.db import models
-from django.db.models.fields import FieldDoesNotExist
 from django.utils import six
 from django.utils.encoding import force_text
 from django.utils.translation import ugettext, ugettext_lazy
@@ -226,7 +225,7 @@ class ChangeList(object):
         try:
             field = self.lookup_opts.get_field(field_name)
             return field.name
-        except models.FieldDoesNotExist:
+        except FieldDoesNotExist:
             # See whether field_name is a name of a non-field
             # that allows sorting.
             if callable(field_name):
@@ -377,7 +376,7 @@ class ChangeList(object):
         for field_name in self.list_display:
             try:
                 field = self.lookup_opts.get_field(field_name)
-            except models.FieldDoesNotExist:
+            except FieldDoesNotExist:
                 pass
             else:
                 if isinstance(field.rel, models.ManyToOneRel):

+ 1 - 1
django/contrib/contenttypes/admin.py

@@ -9,7 +9,7 @@ from django.contrib.contenttypes.forms import (
     BaseGenericInlineFormSet, generic_inlineformset_factory
 )
 from django.core import checks
-from django.db.models.fields import FieldDoesNotExist
+from django.core.exceptions import FieldDoesNotExist
 from django.forms import ALL_FIELDS
 from django.forms.models import modelform_defines_fields
 

+ 2 - 2
django/contrib/contenttypes/fields.py

@@ -3,10 +3,10 @@ from __future__ import unicode_literals
 from collections import defaultdict
 
 from django.core import checks
-from django.core.exceptions import ObjectDoesNotExist
+from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist
 from django.db import connection
 from django.db import models, router, transaction, DEFAULT_DB_ALIAS
-from django.db.models import signals, FieldDoesNotExist, DO_NOTHING
+from django.db.models import signals, DO_NOTHING
 from django.db.models.base import ModelBase
 from django.db.models.fields.related import ForeignObject, ForeignObjectRel
 from django.db.models.query_utils import PathInfo

+ 1 - 1
django/contrib/gis/db/models/lookups.py

@@ -1,8 +1,8 @@
 from __future__ import unicode_literals
 import re
 
+from django.core.exceptions import FieldDoesNotExist
 from django.db.models.constants import LOOKUP_SEP
-from django.db.models.fields import FieldDoesNotExist
 from django.db.models.lookups import Lookup
 from django.db.models.expressions import ExpressionNode, Col
 from django.utils import six

+ 1 - 1
django/contrib/gis/sitemaps/views.py

@@ -4,8 +4,8 @@ from django.apps import apps
 from django.http import Http404
 from django.contrib.gis.db.models.fields import GeometryField
 from django.contrib.gis.shortcuts import render_to_kml, render_to_kmz
+from django.core.exceptions import FieldDoesNotExist
 from django.db import connections, DEFAULT_DB_ALIAS
-from django.db.models.fields import FieldDoesNotExist
 
 
 def kml(request, label, model, field_name=None, compress=False, using=DEFAULT_DB_ALIAS):

+ 3 - 3
django/contrib/gis/utils/layermapping.py

@@ -8,7 +8,7 @@
 """
 import sys
 from decimal import Decimal, InvalidOperation as DecimalInvalidOperation
-from django.core.exceptions import ObjectDoesNotExist
+from django.core.exceptions import FieldDoesNotExist, ObjectDoesNotExist
 from django.db import connections, router
 from django.contrib.gis.db.models import GeometryField
 from django.contrib.gis.gdal import (CoordTransform, DataSource,
@@ -189,7 +189,7 @@ class LayerMapping(object):
             # for the given field name in the mapping.
             try:
                 model_field = self.model._meta.get_field(field_name)
-            except models.fields.FieldDoesNotExist:
+            except FieldDoesNotExist:
                 raise LayerMapError('Given mapping field "%s" not in given Model fields.' % field_name)
 
             # Getting the string name for the Django field class (e.g., 'PointField').
@@ -231,7 +231,7 @@ class LayerMapping(object):
                         idx = check_ogr_fld(ogr_field)
                         try:
                             rel_model._meta.get_field(rel_name)
-                        except models.fields.FieldDoesNotExist:
+                        except FieldDoesNotExist:
                             raise LayerMapError('ForeignKey mapping field "%s" not in %s fields.' %
                                                 (rel_name, rel_model.__class__.__name__))
                     fields_val = rel_model

+ 1 - 1
django/contrib/sites/managers.py

@@ -3,8 +3,8 @@ from __future__ import unicode_literals
 
 from django.conf import settings
 from django.core import checks
+from django.core.exceptions import FieldDoesNotExist
 from django.db import models
-from django.db.models.fields import FieldDoesNotExist
 
 
 class CurrentSiteManager(models.Manager):

+ 5 - 0
django/core/exceptions.py

@@ -5,6 +5,11 @@ from django.utils import six
 from django.utils.encoding import force_text
 
 
+class FieldDoesNotExist(Exception):
+    """The requested model field does not exist"""
+    pass
+
+
 class DjangoRuntimeWarning(RuntimeWarning):
     pass
 

+ 3 - 5
django/db/models/base.py

@@ -9,14 +9,14 @@ from django.apps import apps
 from django.apps.config import MODELS_MODULE_NAME
 from django.conf import settings
 from django.core import checks
-from django.core.exceptions import (ObjectDoesNotExist,
+from django.core.exceptions import (FieldDoesNotExist, ObjectDoesNotExist,
     MultipleObjectsReturned, FieldError, ValidationError, NON_FIELD_ERRORS)
 from django.db import (router, connections, transaction, DatabaseError,
     DEFAULT_DB_ALIAS, DJANGO_VERSION_PICKLE_KEY)
 from django.db.models import signals
 from django.db.models.constants import LOOKUP_SEP
 from django.db.models.deletion import Collector
-from django.db.models.fields import AutoField, FieldDoesNotExist
+from django.db.models.fields import AutoField
 from django.db.models.fields.related import (ForeignObjectRel, ManyToOneRel,
     OneToOneField, add_lazy_relation)
 from django.db.models.manager import ensure_default_manager
@@ -1443,7 +1443,7 @@ class Model(six.with_metaclass(ModelBase)):
             try:
                 field = cls._meta.get_field(field_name,
                     many_to_many=True)
-            except models.FieldDoesNotExist:
+            except FieldDoesNotExist:
                 errors.append(
                     checks.Error(
                         "'%s' refers to the non-existent field '%s'." % (option, field_name),
@@ -1485,8 +1485,6 @@ class Model(six.with_metaclass(ModelBase)):
         """ Check "ordering" option -- is it a list of strings and do all fields
         exist? """
 
-        from django.db.models import FieldDoesNotExist
-
         if not cls._meta.ordering:
             return []
 

+ 3 - 4
django/db/models/fields/__init__.py

@@ -31,6 +31,9 @@ from django.utils.ipv6 import clean_ipv6_address
 from django.utils import six
 from django.utils.itercompat import is_iterable
 
+# imported for backwards compatibility
+from django.core.exceptions import FieldDoesNotExist  # NOQA
+
 # Avoid "TypeError: Item in ``from list'' not a string" -- unicode_literals
 # makes these strings unicode
 __all__ = [str(x) for x in (
@@ -61,10 +64,6 @@ def _load_field(app_label, model_name, field_name):
     return apps.get_model(app_label, model_name)._meta.get_field_by_name(field_name)[0]
 
 
-class FieldDoesNotExist(Exception):
-    pass
-
-
 # A guide to Field parameters:
 #
 #   * name:      The name of the field specified in the model.

+ 2 - 2
django/db/models/fields/related.py

@@ -5,13 +5,13 @@ import warnings
 
 from django.apps import apps
 from django.core import checks
+from django.core.exceptions import FieldDoesNotExist
 from django.db import connection, connections, router, transaction
 from django.db.backends import utils
 from django.db.models import signals, Q
 from django.db.models.deletion import SET_NULL, SET_DEFAULT, CASCADE
 from django.db.models.fields import (AutoField, Field, IntegerField,
-    PositiveIntegerField, PositiveSmallIntegerField, FieldDoesNotExist,
-    BLANK_CHOICE_DASH)
+    PositiveIntegerField, PositiveSmallIntegerField, BLANK_CHOICE_DASH)
 from django.db.models.lookups import IsNull
 from django.db.models.query import QuerySet
 from django.db.models.query_utils import PathInfo

+ 1 - 1
django/db/models/manager.py

@@ -2,9 +2,9 @@ import copy
 from importlib import import_module
 import inspect
 
+from django.core.exceptions import FieldDoesNotExist
 from django.db import router
 from django.db.models.query import QuerySet
-from django.db.models.fields import FieldDoesNotExist
 from django.utils import six
 from django.utils.encoding import python_2_unicode_compatible
 

+ 2 - 1
django/db/models/options.py

@@ -5,8 +5,9 @@ from collections import OrderedDict
 
 from django.apps import apps
 from django.conf import settings
+from django.core.exceptions import FieldDoesNotExist
 from django.db.models.fields.related import ManyToManyRel
-from django.db.models.fields import AutoField, FieldDoesNotExist
+from django.db.models.fields import AutoField
 from django.db.models.fields.proxy import OrderWrt
 from django.utils import six
 from django.utils.encoding import force_text, smart_text, python_2_unicode_compatible

+ 1 - 1
django/db/models/query_utils.py

@@ -10,6 +10,7 @@ from __future__ import unicode_literals
 from collections import namedtuple
 
 from django.apps import apps
+from django.core.exceptions import FieldDoesNotExist
 from django.db.backends import utils
 from django.db.models.constants import LOOKUP_SEP
 from django.utils import six
@@ -99,7 +100,6 @@ class DeferredAttribute(object):
         Retrieves and caches the value from the datastore on the first lookup.
         Returns the cached value.
         """
-        from django.db.models.fields import FieldDoesNotExist
         non_deferred_model = instance._meta.proxy_for_model
         opts = non_deferred_model._meta
 

+ 1 - 2
django/db/models/sql/query.py

@@ -13,12 +13,11 @@ from collections import Mapping, OrderedDict
 import copy
 import warnings
 
-from django.core.exceptions import FieldError
+from django.core.exceptions import FieldDoesNotExist, FieldError
 from django.db import connections, DEFAULT_DB_ALIAS
 from django.db.models.aggregates import Count
 from django.db.models.constants import LOOKUP_SEP
 from django.db.models.expressions import Col, Ref
-from django.db.models.fields import FieldDoesNotExist
 from django.db.models.query_utils import PathInfo, Q, refs_aggregate
 from django.db.models.sql.constants import (QUERY_TERMS, ORDER_DIR, SINGLE,
         ORDER_PATTERN, SelectInfo, INNER, LOUTER)

+ 13 - 0
docs/ref/exceptions.txt

@@ -33,6 +33,19 @@ ObjectDoesNotExist and DoesNotExist
     See :meth:`~django.db.models.query.QuerySet.get()` for further information
     on :exc:`ObjectDoesNotExist` and :exc:`DoesNotExist`.
 
+FieldDoesNotExist
+-----------------
+.. exception:: FieldDoesNotExist
+
+    The ``FieldDoesNotExist`` exception is raised by a model's
+    ``_meta.get_field()`` method when the requested field does not exist on the
+    model or on the model's parents.
+
+    .. versionchanged:: 1.8
+
+        This exception was previously defined only in
+        ``django.db.models.fields`` and wasn't part of the public API.
+
 MultipleObjectsReturned
 -----------------------
 .. exception:: MultipleObjectsReturned

+ 1 - 2
tests/annotations/tests.py

@@ -2,12 +2,11 @@ from __future__ import unicode_literals
 import datetime
 from decimal import Decimal
 
-from django.core.exceptions import FieldError
+from django.core.exceptions import FieldDoesNotExist, FieldError
 from django.db.models import (
     Sum, Count,
     F, Value, Func,
     IntegerField, BooleanField, CharField)
-from django.db.models.fields import FieldDoesNotExist
 from django.test import TestCase
 from django.utils import six
 

+ 2 - 2
tests/model_meta/test.py

@@ -1,7 +1,7 @@
 from django import test
-
-from django.db.models.fields import related, CharField, Field, FieldDoesNotExist
 from django.contrib.contenttypes.fields import GenericRelation
+from django.core.exceptions import FieldDoesNotExist
+from django.db.models.fields import related, CharField, Field
 
 from .models import (
     AbstractPerson, BasePerson, Person, Relating, Relation