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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. from django.core.exceptions import ImproperlyConfigured
  2. from django.db.models.fields import CharField, DecimalField, Field
  3. from django.db.models import SubfieldBase
  4. from django.utils import six
  5. from django.utils.translation import ugettext_lazy as _
  6. from django.core.validators import MaxLengthValidator
  7. from oscar.core import validators
  8. from oscar.forms import fields
  9. import oscar.core.phonenumber as phonenumber
  10. try:
  11. from south.modelsinspector import add_introspection_rules
  12. except ImportError:
  13. pass
  14. else:
  15. add_introspection_rules([], ["^oscar\.models\.fields\.ExtendedURLField$"])
  16. add_introspection_rules([], [
  17. "^oscar\.models\.fields\.PositiveDecimalField$"])
  18. add_introspection_rules([], [
  19. "^oscar\.models\.fields\.UppercaseCharField$"])
  20. add_introspection_rules([], [
  21. "^oscar\.models\.fields\.PhoneNumberField$"])
  22. class ExtendedURLField(CharField):
  23. description = _("URL")
  24. def __init__(self, verbose_name=None, name=None,
  25. verify_exists=None, **kwargs):
  26. kwargs['max_length'] = kwargs.get('max_length', 200)
  27. CharField.__init__(self, verbose_name, name, **kwargs)
  28. # 'verify_exists' was deprecated in Django 1.4. To ensure backwards
  29. # compatibility, it is still accepted here, but only passed
  30. # on to the parent class if it was specified.
  31. self.verify_exists = verify_exists
  32. if verify_exists is not None:
  33. validator = validators.ExtendedURLValidator(
  34. verify_exists=verify_exists)
  35. else:
  36. validator = validators.ExtendedURLValidator()
  37. self.validators.append(validator)
  38. def formfield(self, **kwargs):
  39. # As with CharField, this will cause URL validation to be performed
  40. # twice.
  41. defaults = {
  42. 'form_class': fields.ExtendedURLField,
  43. 'verify_exists': self.verify_exists
  44. }
  45. defaults.update(kwargs)
  46. return super(ExtendedURLField, self).formfield(**defaults)
  47. class PositiveDecimalField(DecimalField):
  48. """
  49. A simple subclass of ``django.db.models.fields.DecimalField`` that
  50. restricts values to be non-negative.
  51. """
  52. def formfield(self, **kwargs):
  53. return super(PositiveDecimalField, self).formfield(min_value=0)
  54. class UppercaseCharField(CharField):
  55. """
  56. A simple subclass of ``django.db.models.fields.CharField`` that
  57. restricts all text to be uppercase.
  58. """
  59. # necessary for to_python to be called
  60. __metaclass__ = SubfieldBase
  61. def to_python(self, value):
  62. val = super(UppercaseCharField, self).to_python(value)
  63. if isinstance(val, six.string_types):
  64. return val.upper()
  65. else:
  66. return val
  67. class PhoneNumberField(Field):
  68. """
  69. An international phone number.
  70. * Validates a wide range of phone number formats
  71. * Displays it nicely formatted
  72. * Can be given a hint for the country, so that it can accept local numbers,
  73. that are not in an international format
  74. Note:
  75. This field is based on work in django-phonenumber-field:
  76. https://github.com/maikhoepfel/django-phonenumber-field/
  77. See ``oscar/core/phonenumber.py`` for the relevant copyright and
  78. permission notice.
  79. """
  80. attr_class = phonenumber.PhoneNumber
  81. descriptor_class = phonenumber.PhoneNumberDescriptor
  82. default_validators = [phonenumber.validate_international_phonenumber]
  83. description = _("Phone number")
  84. def __init__(self, *args, **kwargs):
  85. if kwargs.get('null', False):
  86. raise ImproperlyConfigured(
  87. "null=True is not supported on PhoneNumberField")
  88. kwargs['max_length'] = kwargs.get('max_length', 128)
  89. super(PhoneNumberField, self).__init__(*args, **kwargs)
  90. self.validators.append(MaxLengthValidator(self.max_length))
  91. def get_internal_type(self):
  92. return "CharField"
  93. def get_prep_value(self, value):
  94. """
  95. Returns field's value prepared for saving into a database.
  96. """
  97. value = phonenumber.to_python(value)
  98. if value is None:
  99. return ''
  100. return value.as_e164 if value.is_valid() else value.raw_input
  101. def contribute_to_class(self, cls, name):
  102. super(PhoneNumberField, self).contribute_to_class(cls, name)
  103. setattr(cls, self.name, self.descriptor_class(self))