You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

validators.py 3.1KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. from django.core import validators
  2. from django.core.exceptions import ValidationError
  3. from django.core.urlresolvers import resolve
  4. from django.db.models import get_model
  5. from django.http import Http404
  6. from django.utils.translation import ugettext_lazy as _
  7. class ExtendedURLValidator(validators.URLValidator):
  8. def __call__(self, value):
  9. try:
  10. super(ExtendedURLValidator, self).__call__(value)
  11. except ValidationError:
  12. if value:
  13. self.validate_local_url(value)
  14. else:
  15. raise
  16. def validate_local_url(self, value):
  17. """
  18. Validate local URL name
  19. """
  20. try:
  21. value = self.fix_local_url(value)
  22. if self.verify_exists:
  23. resolve(value)
  24. self.is_local_url = True
  25. except Http404:
  26. # We load flatpages here as it causes a circular reference problem
  27. # sometimes. FlatPages is None if not installed
  28. FlatPage = get_model('flatpages', 'FlatPage')
  29. if FlatPage is not None:
  30. for page in FlatPage.objects.all().only(('url')):
  31. if value == page.url:
  32. return
  33. raise ValidationError(_('Specified page does not exist'))
  34. def fix_local_url(self, value):
  35. """
  36. Puts preceding and trailing slashes to local URL name
  37. """
  38. if value != '/':
  39. value = '/' + value.lstrip('/')
  40. q_index = value.find('?')
  41. if q_index > 0:
  42. value = value[:q_index]
  43. return value
  44. class URLDoesNotExistValidator(ExtendedURLValidator):
  45. def __call__(self, value):
  46. """
  47. Validate that the URL in *value* does not already exist. The
  48. URL will be verified first and raises ``ValidationError`` when
  49. it is invalid. A valid URL is checked for existance and raises
  50. ``ValidationError`` if the URL already exists. Setting attribute
  51. ``verify_exists`` has no impact on validation.
  52. This validation uses two calls to ExtendedURLValidator which can
  53. be slow. Be aware of this, when you use it.
  54. Returns ``None`` if URL is valid and does not exist.
  55. """
  56. self.verify_exists = False
  57. # calling ExtendedURLValidator twice instead of replicating its code
  58. # and invert the cases when a ValidationError is returned seemes to
  59. # be a much cleaner solution. Although this might not be the most
  60. # efficient way of handling this, it should have not much of an impact
  61. # due to its current application in flatpage creation.
  62. try:
  63. super(URLDoesNotExistValidator, self).__call__(value)
  64. except ValidationError:
  65. raise ValidationError(_('Specified page does already exist'),
  66. code='invalid')
  67. # check if URL exists since it seems to be valid
  68. try:
  69. self.verify_exists = True
  70. super(URLDoesNotExistValidator, self).__call__(value)
  71. except ValidationError:
  72. return
  73. raise ValidationError(_('Specified page does already exist'),
  74. code='invalid')