exceptions.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. """
  2. Global Django exception and warning classes.
  3. """
  4. from functools import reduce
  5. import operator
  6. from django.utils import six
  7. from django.utils.encoding import force_text
  8. class DjangoRuntimeWarning(RuntimeWarning):
  9. pass
  10. class AppRegistryNotReady(Exception):
  11. """The django.apps registry is not populated yet"""
  12. pass
  13. class ObjectDoesNotExist(Exception):
  14. """The requested object does not exist"""
  15. silent_variable_failure = True
  16. class MultipleObjectsReturned(Exception):
  17. """The query returned multiple objects when only one was expected."""
  18. pass
  19. class SuspiciousOperation(Exception):
  20. """The user did something suspicious"""
  21. class SuspiciousMultipartForm(SuspiciousOperation):
  22. """Suspect MIME request in multipart form data"""
  23. pass
  24. class SuspiciousFileOperation(SuspiciousOperation):
  25. """A Suspicious filesystem operation was attempted"""
  26. pass
  27. class DisallowedHost(SuspiciousOperation):
  28. """HTTP_HOST header contains invalid value"""
  29. pass
  30. class DisallowedRedirect(SuspiciousOperation):
  31. """Redirect to scheme not in allowed list"""
  32. pass
  33. class PermissionDenied(Exception):
  34. """The user did not have permission to do that"""
  35. pass
  36. class ViewDoesNotExist(Exception):
  37. """The requested view does not exist"""
  38. pass
  39. class MiddlewareNotUsed(Exception):
  40. """This middleware is not used in this server configuration"""
  41. pass
  42. class ImproperlyConfigured(Exception):
  43. """Django is somehow improperly configured"""
  44. pass
  45. class FieldError(Exception):
  46. """Some kind of problem with a model field."""
  47. pass
  48. NON_FIELD_ERRORS = '__all__'
  49. class ValidationError(Exception):
  50. """An error while validating data."""
  51. def __init__(self, message, code=None, params=None):
  52. """
  53. The `message` argument can be a single error, a list of errors, or a
  54. dictionary that maps field names to lists of errors. What we define as
  55. an "error" can be either a simple string or an instance of
  56. ValidationError with its message attribute set, and what we define as
  57. list or dictionary can be an actual `list` or `dict` or an instance
  58. of ValidationError with its `error_list` or `error_dict` attribute set.
  59. """
  60. # PY2 can't pickle naive exception: http://bugs.python.org/issue1692335.
  61. super(ValidationError, self).__init__(message, code, params)
  62. if isinstance(message, ValidationError):
  63. if hasattr(message, 'error_dict'):
  64. message = message.error_dict
  65. # PY2 has a `message` property which is always there so we can't
  66. # duck-type on it. It was introduced in Python 2.5 and already
  67. # deprecated in Python 2.6.
  68. elif not hasattr(message, 'message' if six.PY3 else 'code'):
  69. message = message.error_list
  70. else:
  71. message, code, params = message.message, message.code, message.params
  72. if isinstance(message, dict):
  73. self.error_dict = {}
  74. for field, messages in message.items():
  75. if not isinstance(messages, ValidationError):
  76. messages = ValidationError(messages)
  77. self.error_dict[field] = messages.error_list
  78. elif isinstance(message, list):
  79. self.error_list = []
  80. for message in message:
  81. # Normalize plain strings to instances of ValidationError.
  82. if not isinstance(message, ValidationError):
  83. message = ValidationError(message)
  84. self.error_list.extend(message.error_list)
  85. else:
  86. self.message = message
  87. self.code = code
  88. self.params = params
  89. self.error_list = [self]
  90. @property
  91. def message_dict(self):
  92. # Trigger an AttributeError if this ValidationError
  93. # doesn't have an error_dict.
  94. getattr(self, 'error_dict')
  95. return dict(self)
  96. @property
  97. def messages(self):
  98. if hasattr(self, 'error_dict'):
  99. return reduce(operator.add, dict(self).values())
  100. return list(self)
  101. def update_error_dict(self, error_dict):
  102. if hasattr(self, 'error_dict'):
  103. for field, error_list in self.error_dict.items():
  104. error_dict.setdefault(field, []).extend(error_list)
  105. else:
  106. error_dict.setdefault(NON_FIELD_ERRORS, []).extend(self.error_list)
  107. return error_dict
  108. def __iter__(self):
  109. if hasattr(self, 'error_dict'):
  110. for field, errors in self.error_dict.items():
  111. yield field, list(ValidationError(errors))
  112. else:
  113. for error in self.error_list:
  114. message = error.message
  115. if error.params:
  116. message %= error.params
  117. yield force_text(message)
  118. def __str__(self):
  119. if hasattr(self, 'error_dict'):
  120. return repr(dict(self))
  121. return repr(list(self))
  122. def __repr__(self):
  123. return 'ValidationError(%s)' % self