exceptions.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. """
  2. Global Django exception and warning classes.
  3. """
  4. import operator
  5. from django.utils.hashable import make_hashable
  6. class FieldDoesNotExist(Exception):
  7. """The requested model field does not exist"""
  8. pass
  9. class AppRegistryNotReady(Exception):
  10. """The django.apps registry is not populated yet"""
  11. pass
  12. class ObjectDoesNotExist(Exception):
  13. """The requested object does not exist"""
  14. silent_variable_failure = True
  15. class MultipleObjectsReturned(Exception):
  16. """The query returned multiple objects when only one was expected."""
  17. pass
  18. class SuspiciousOperation(Exception):
  19. """The user did something suspicious"""
  20. class SuspiciousMultipartForm(SuspiciousOperation):
  21. """Suspect MIME request in multipart form data"""
  22. pass
  23. class SuspiciousFileOperation(SuspiciousOperation):
  24. """A Suspicious filesystem operation was attempted"""
  25. pass
  26. class DisallowedHost(SuspiciousOperation):
  27. """HTTP_HOST header contains invalid value"""
  28. pass
  29. class DisallowedRedirect(SuspiciousOperation):
  30. """Redirect to scheme not in allowed list"""
  31. pass
  32. class TooManyFieldsSent(SuspiciousOperation):
  33. """
  34. The number of fields in a GET or POST request exceeded
  35. settings.DATA_UPLOAD_MAX_NUMBER_FIELDS.
  36. """
  37. pass
  38. class TooManyFilesSent(SuspiciousOperation):
  39. """
  40. The number of fields in a GET or POST request exceeded
  41. settings.DATA_UPLOAD_MAX_NUMBER_FILES.
  42. """
  43. pass
  44. class RequestDataTooBig(SuspiciousOperation):
  45. """
  46. The size of the request (excluding any file uploads) exceeded
  47. settings.DATA_UPLOAD_MAX_MEMORY_SIZE.
  48. """
  49. pass
  50. class RequestAborted(Exception):
  51. """The request was closed before it was completed, or timed out."""
  52. pass
  53. class BadRequest(Exception):
  54. """The request is malformed and cannot be processed."""
  55. pass
  56. class PermissionDenied(Exception):
  57. """The user did not have permission to do that"""
  58. pass
  59. class ViewDoesNotExist(Exception):
  60. """The requested view does not exist"""
  61. pass
  62. class MiddlewareNotUsed(Exception):
  63. """This middleware is not used in this server configuration"""
  64. pass
  65. class ImproperlyConfigured(Exception):
  66. """Django is somehow improperly configured"""
  67. pass
  68. class FieldError(Exception):
  69. """Some kind of problem with a model field."""
  70. pass
  71. NON_FIELD_ERRORS = "__all__"
  72. class ValidationError(Exception):
  73. """An error while validating data."""
  74. def __init__(self, message, code=None, params=None):
  75. """
  76. The `message` argument can be a single error, a list of errors, or a
  77. dictionary that maps field names to lists of errors. What we define as
  78. an "error" can be either a simple string or an instance of
  79. ValidationError with its message attribute set, and what we define as
  80. list or dictionary can be an actual `list` or `dict` or an instance
  81. of ValidationError with its `error_list` or `error_dict` attribute set.
  82. """
  83. super().__init__(message, code, params)
  84. if isinstance(message, ValidationError):
  85. if hasattr(message, "error_dict"):
  86. message = message.error_dict
  87. elif not hasattr(message, "message"):
  88. message = message.error_list
  89. else:
  90. message, code, params = message.message, message.code, message.params
  91. if isinstance(message, dict):
  92. self.error_dict = {}
  93. for field, messages in message.items():
  94. if not isinstance(messages, ValidationError):
  95. messages = ValidationError(messages)
  96. self.error_dict[field] = messages.error_list
  97. elif isinstance(message, list):
  98. self.error_list = []
  99. for message in message:
  100. # Normalize plain strings to instances of ValidationError.
  101. if not isinstance(message, ValidationError):
  102. message = ValidationError(message)
  103. if hasattr(message, "error_dict"):
  104. self.error_list.extend(sum(message.error_dict.values(), []))
  105. else:
  106. self.error_list.extend(message.error_list)
  107. else:
  108. self.message = message
  109. self.code = code
  110. self.params = params
  111. self.error_list = [self]
  112. @property
  113. def message_dict(self):
  114. # Trigger an AttributeError if this ValidationError
  115. # doesn't have an error_dict.
  116. getattr(self, "error_dict")
  117. return dict(self)
  118. @property
  119. def messages(self):
  120. if hasattr(self, "error_dict"):
  121. return sum(dict(self).values(), [])
  122. return list(self)
  123. def update_error_dict(self, error_dict):
  124. if hasattr(self, "error_dict"):
  125. for field, error_list in self.error_dict.items():
  126. error_dict.setdefault(field, []).extend(error_list)
  127. else:
  128. error_dict.setdefault(NON_FIELD_ERRORS, []).extend(self.error_list)
  129. return error_dict
  130. def __iter__(self):
  131. if hasattr(self, "error_dict"):
  132. for field, errors in self.error_dict.items():
  133. yield field, list(ValidationError(errors))
  134. else:
  135. for error in self.error_list:
  136. message = error.message
  137. if error.params:
  138. message %= error.params
  139. yield str(message)
  140. def __str__(self):
  141. if hasattr(self, "error_dict"):
  142. return repr(dict(self))
  143. return repr(list(self))
  144. def __repr__(self):
  145. return "ValidationError(%s)" % self
  146. def __eq__(self, other):
  147. if not isinstance(other, ValidationError):
  148. return NotImplemented
  149. return hash(self) == hash(other)
  150. def __hash__(self):
  151. if hasattr(self, "message"):
  152. return hash(
  153. (
  154. self.message,
  155. self.code,
  156. make_hashable(self.params),
  157. )
  158. )
  159. if hasattr(self, "error_dict"):
  160. return hash(make_hashable(self.error_dict))
  161. return hash(tuple(sorted(self.error_list, key=operator.attrgetter("message"))))
  162. class EmptyResultSet(Exception):
  163. """A database query predicate is impossible."""
  164. pass
  165. class FullResultSet(Exception):
  166. """A database query predicate is matches everything."""
  167. pass
  168. class SynchronousOnlyOperation(Exception):
  169. """The user tried to call a sync-only function from an async context."""
  170. pass