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.

phonenumber.py 4.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. from django.core import validators
  2. from django.conf import settings
  3. from django.core.exceptions import ValidationError
  4. from django.utils.translation import ugettext_lazy as _
  5. import phonenumbers
  6. class PhoneNumber(phonenumbers.phonenumber.PhoneNumber):
  7. """
  8. A extended version of phonenumbers.phonenumber.PhoneNumber that provides some neat and more pythonic, easy
  9. to access methods. This makes using a PhoneNumber instance much easier, especially in templates and such.
  10. """
  11. format_map = {
  12. 'E164': phonenumbers.PhoneNumberFormat.E164,
  13. 'INTERNATIONAL': phonenumbers.PhoneNumberFormat.INTERNATIONAL,
  14. 'NATIONAL': phonenumbers.PhoneNumberFormat.NATIONAL,
  15. 'RFC3966': phonenumbers.PhoneNumberFormat.RFC3966,
  16. }
  17. @classmethod
  18. def from_string(cls, phone_number, region=None):
  19. phone_number_obj = cls()
  20. if region is None:
  21. region = getattr(settings, 'PHONENUMBER_DEFAULT_REGION', None)
  22. phonenumbers.parse(number=phone_number, region=region,
  23. keep_raw_input=True, numobj=phone_number_obj)
  24. return phone_number_obj
  25. def __unicode__(self):
  26. format_string = getattr(
  27. settings, 'PHONENUMBER_DEFAULT_FORMAT', 'INTERNATIONAL')
  28. fmt = self.format_map[format_string]
  29. if self.is_valid():
  30. return self.format_as(fmt)
  31. return self.raw_input
  32. def __str__(self):
  33. return str(unicode(self))
  34. def original_unicode(self):
  35. return super(PhoneNumber, self).__unicode__()
  36. def is_valid(self):
  37. """
  38. checks whether the number supplied is actually valid
  39. """
  40. return phonenumbers.is_valid_number(self)
  41. def format_as(self, format):
  42. if self.is_valid():
  43. return phonenumbers.format_number(self, format)
  44. else:
  45. return self.raw_input
  46. @property
  47. def as_international(self):
  48. return self.format_as(phonenumbers.PhoneNumberFormat.INTERNATIONAL)
  49. @property
  50. def as_e164(self):
  51. return self.format_as(phonenumbers.PhoneNumberFormat.E164)
  52. @property
  53. def as_national(self):
  54. return self.format_as(phonenumbers.PhoneNumberFormat.NATIONAL)
  55. @property
  56. def as_rfc3966(self):
  57. return self.format_as(phonenumbers.PhoneNumberFormat.RFC3966)
  58. def __len__(self):
  59. return len(self.__unicode__())
  60. def __eq__(self, other):
  61. if type(other) == PhoneNumber:
  62. return self.as_e164 == other.as_e164
  63. else:
  64. return super(PhoneNumber, self).__eq__(other)
  65. def to_python(value):
  66. if value in validators.EMPTY_VALUES: # None or ''
  67. phone_number = None
  68. elif value and isinstance(value, basestring):
  69. try:
  70. phone_number = PhoneNumber.from_string(phone_number=value)
  71. except phonenumbers.phonenumberutil.NumberParseException, e:
  72. # the string provided is not a valid PhoneNumber.
  73. phone_number = PhoneNumber(raw_input=value)
  74. elif isinstance(value, PhoneNumber):
  75. phone_number = value
  76. return phone_number
  77. class PhoneNumberDescriptor(object):
  78. """
  79. The descriptor for the phone number attribute on the model instance. Returns a PhoneNumber when accessed so you can
  80. do stuff like::
  81. >>> instance.phone_number.as_international
  82. Assigns a phone number object on assignment so you can do::
  83. >>> instance.phone_number = PhoneNumber(...)
  84. or
  85. >>> instance.phone_number = '+414204242'
  86. """
  87. def __init__(self, field):
  88. self.field = field
  89. def __get__(self, instance=None, owner=None):
  90. if instance is None:
  91. raise AttributeError(
  92. "The '%s' attribute can only be accessed from %s instances."
  93. % (self.field.name, owner.__name__))
  94. return instance.__dict__[self.field.name]
  95. def __set__(self, instance, value):
  96. instance.__dict__[self.field.name] = to_python(value)
  97. def validate_international_phonenumber(value):
  98. phone_number = to_python(value)
  99. if phone_number and not phone_number.is_valid():
  100. raise ValidationError(_(u'The phone number entered is not valid.'))