.. testsetup:: * import django from bs4 import BeautifulSoup django.setup() def print_html(html): print(BeautifulSoup(html).prettify().strip()) def print_html_compact(html): output = BeautifulSoup(html).prettify().strip().splitlines() print("\n".join(output[:15])) print(" ...") print("\n".join(output[-7:])) The PhoneNumber wrapper ======================= .. autoclass:: phonenumber_field.phonenumber.PhoneNumber() .. automethod:: phonenumber_field.phonenumber.PhoneNumber.from_string .. automethod:: phonenumber_field.phonenumber.PhoneNumber.is_valid .. autoproperty:: phonenumber_field.phonenumber.PhoneNumber.as_international .. autoproperty:: phonenumber_field.phonenumber.PhoneNumber.as_national .. autoproperty:: phonenumber_field.phonenumber.PhoneNumber.as_e164 .. autoproperty:: phonenumber_field.phonenumber.PhoneNumber.as_rfc3966 Usage ----- .. doctest:: wrapper >>> from phonenumber_field.phonenumber import PhoneNumber >>> number = PhoneNumber.from_string("+16044011234") >>> print(number.as_national) (604) 401-1234 >>> print(number.as_e164) +16044011234 >>> print(number.as_international) +1 604-401-1234 >>> print(number.as_rfc3966) tel:+1-604-401-1234 # Using national numbers with the region keyword argument. >>> canadian_number = "(604) 401 1234" >>> number = PhoneNumber.from_string(canadian_number, region="CA") >>> print(number.as_e164) +16044011234 Model field =========== The :class:`~phonenumber_field.modelfields.PhoneNumberField` :ref:`model field ` allows storing :class:`~phonenumber_field.phonenumber.PhoneNumber`\ s in the database, based on a :class:`~django.db.models.CharField`. The phone number format used by the database is controlled with :setting:`PHONENUMBER_DB_FORMAT`. When no region is specified, a phone number in the ``"NATIONAL"`` format will be assumed to be from the :setting:`PHONENUMBER_DEFAULT_REGION`. - The default :ref:`form field ` for this field is the :class:`~phonenumber_field.formfields.PhoneNumberField`. - The default :ref:`form widget ` for this field is the :class:`~phonenumber_field.widgets.RegionalPhoneNumberWidget`. .. autoclass:: phonenumber_field.modelfields.PhoneNumberField .. automethod:: __init__ Usage ----- .. code-block:: python from django.db import models from phonenumber_field.modelfields import PhoneNumberField class Customer(models.Model): name = models.TextField() # An optional phone number. phone_number = PhoneNumberField(blank=True) Form fields =========== :class:`~phonenumber_field.formfields.PhoneNumberField` ------------------------------------------------------- The :class:`~phonenumber_field.formfields.PhoneNumberField` :ref:`form field ` to validate :class:`~phonenumber_field.phonenumber.PhoneNumber`, based on a :class:`~django.forms.CharField`. - Default widget: :class:`~phonenumber_field.widgets.RegionalPhoneNumberWidget` - Empty value: ``""`` - Normalizes to: A :class:`~phonenumber_field.phonenumber.PhoneNumber` or an empty :class:`str` (``""``) - Uses :func:`~phonenumber_field.validators.validate_international_phonenumber` .. autoclass:: phonenumber_field.formfields.PhoneNumberField .. automethod:: __init__ Usage ~~~~~ .. doctest:: formfield >>> from phonenumber_field.formfields import PhoneNumberField >>> class PhoneForm(django.forms.Form): ... number = PhoneNumberField(region="CA") ... # Manipulating data >>> form = PhoneForm({"number": "+1 604 401 1234"}) >>> form.is_valid() True >>> form.cleaned_data {'number': PhoneNumber(country_code=1, national_number=6044011234, extension=None, italian_leading_zero=None, number_of_leading_zeros=None, country_code_source=1, preferred_domestic_carrier_code=None)} >>> print_html(form.as_div())
# Handling errors >>> form = PhoneForm({"number": "invalid"}) >>> form.is_valid() False >>> print_html(form.as_div())
  • Enter a valid phone number (e.g. (506) 234-5678) or a number with an international call prefix.
.. note:: Because the PhoneNumberField specifies a region, the example number is a national number from that region. When no region is specified, an international example phone number in the E.164 format is suggested. :class:`~phonenumber_field.formfields.SplitPhoneNumberField` ------------------------------------------------------------ A :class:`~django.forms.MultiValueField` that offers: - a ```` to enter the phone number. To customize each field, subclass :class:`~phonenumber_field.formfields.SplitPhoneNumberField` and override: - :func:`~phonenumber_field.formfields.SplitPhoneNumberField.prefix_field` for the phone number prefix field, - :func:`~phonenumber_field.formfields.SplitPhoneNumberField.number_field` for the phone number field. This widget uses an example phone number from the selected region for the ``invalid`` key in :attr:`~django.forms.Field.error_messages`, when the region choice is valid. To customize the dynamic message, use :func:`phonenumber_field.formfields.SplitPhoneNumberField.invalid_error_message`. .. important:: Requires the `Babel `_ package. .. autoclass:: phonenumber_field.formfields.SplitPhoneNumberField .. automethod:: __init__ .. automethod:: prefix_field .. automethod:: number_field .. automethod:: invalid_error_message Usage ~~~~~ Simple ...... .. doctest:: SplitPhoneNumberField.basic >>> from phonenumber_field.formfields import SplitPhoneNumberField >>> class PhoneForm(django.forms.Form): ... number = SplitPhoneNumberField() ... >>> form = PhoneForm() >>> print_html_compact(form.as_div())
Number:
Limiting country choices ........................ .. doctest:: SplitPhoneNumberField.country_choices >>> from phonenumber_field.formfields import SplitPhoneNumberField >>> class DemoSplitPhoneNumberField(SplitPhoneNumberField): ... def prefix_field(self): ... return django.forms.ChoiceField(choices=[ ... ("", "---------"), ... ("CA", "Canada"), ... ("FR", "France"), ... ]) ... >>> class LimitedCountryPhoneForm(django.forms.Form): ... number = DemoSplitPhoneNumberField() ... >>> form = LimitedCountryPhoneForm() >>> print_html(form.as_div())
Number:
Pre-selecting a country ....................... .. doctest:: SplitPhoneNumberField.preselecting_country >>> from phonenumber_field.formfields import SplitPhoneNumberField >>> class DemoSplitPhoneNumberField(SplitPhoneNumberField): ... def prefix_field(self): ... return django.forms.ChoiceField(choices=[ ... ("", "---------"), ... ("CA", "Canada"), ... ("FR", "France"), ... ]) ... >>> class FrenchPhoneForm(django.forms.Form): ... number = DemoSplitPhoneNumberField(region="FR") ... >>> form = FrenchPhoneForm() >>> print_html(form.as_div())
Number:
Customizing widget attrs ........................ .. doctest:: SplitPhoneNumberField.preselecting_country >>> from phonenumber_field.formfields import SplitPhoneNumberField >>> class DemoSplitPhoneNumberField(SplitPhoneNumberField): ... def prefix_field(self): ... return django.forms.ChoiceField(choices=[ ... ("", "---------"), ... ("CA", "Canada"), ... ("FR", "France"), ... ]) ... ... def number_field(self): ... number_field = super().number_field() ... number_field.widget.attrs["class"] = "form-control" ... return number_field ... >>> class BootstrapPhoneForm(django.forms.Form): ... number = DemoSplitPhoneNumberField() ... >>> form = BootstrapPhoneForm() >>> print_html(form.as_div())
Number:
Widgets ------- RegionalPhoneNumberWidget ~~~~~~~~~~~~~~~~~~~~~~~~~ **Default widget** for :class:`~phonenumber_field.formfields.PhoneNumberField`. - input_type: ``tel`` - Renders as ```` .. important:: The region should be specified (either per field using the ``region`` keyword argument, or with the :setting:`PHONENUMBER_DEFAULT_REGION` setting) in order to know which national number format to recognize. .. autoclass:: phonenumber_field.widgets.RegionalPhoneNumberWidget .. automethod:: __init__ Usage ..... .. doctest:: fallbackwidget >>> from phonenumber_field.formfields import PhoneNumberField >>> class CanadianPhoneForm(django.forms.Form): ... # RegionalPhoneNumberWidget is the default widget. ... number = PhoneNumberField(region="CA") ... # Using the national format for the field’s region. >>> form = CanadianPhoneForm({"number": "+16044011234"}) >>> print_html(form.as_div())
# Using E164 for an international number. >>> french_number = "+33612345678" >>> form = CanadianPhoneForm({"number": french_number}) >>> print_html(form.as_div())
PhoneNumberPrefixWidget ~~~~~~~~~~~~~~~~~~~~~~~ .. autoclass:: phonenumber_field.widgets.PhoneNumberPrefixWidget Serializer field ================ The :class:`~phonenumber_field.serializersfields.PhoneNumberField` `serializer field `_, based on the `CharField `_. The serialization format is controlled by the :setting:`PHONENUMBER_DEFAULT_FORMAT`. .. autoclass:: phonenumber_field.serializerfields.PhoneNumberField .. automethod:: __init__ Usage ----- .. doctest:: serializerfield >>> from django.conf import settings >>> from rest_framework import renderers, serializers >>> from phonenumber_field.serializerfields import PhoneNumberField >>> class PhoneNumberSerializer(serializers.Serializer): ... number = PhoneNumberField(region="CA") ... >>> serializer = PhoneNumberSerializer(data={"number": "604 401 1234"}) >>> serializer.is_valid() True >>> serializer.validated_data {'number': PhoneNumber(country_code=1, national_number=6044011234, extension=None, italian_leading_zero=None, number_of_leading_zeros=None, country_code_source=20, preferred_domestic_carrier_code=None)} # Using the PHONENUMBER_DEFAULT_FORMAT. >>> renderers.JSONRenderer().render(serializer.data) b'{"number":"+16044011234"}' Validator ========= Validates: - a :class:`~phonenumber_field.phonenumber.PhoneNumber` instance, or - an :class:`str` in an international format (with a prefix), or - an :class:`str` that’s a local phone number according to :setting:`PHONENUMBER_DEFAULT_REGION`. .. note:: Not all well-formed phone numbers are valid. The rules to construct phone numbers vary per region of the world. `Falsehoods Programmers Believe About Phone Numbers `_ is a good read. .. autofunction:: phonenumber_field.validators.validate_international_phonenumber **code**: ``"invalid"`` Settings ======== .. _settings-format-choices: Phone number format choices --------------------------- +------------------------+---------------+------------+-----------------------------------------------------------------+ | Setting value | International | Extensions | Notes | +========================+===============+============+=================================================================+ | ``"E164"`` *(default)* | ✓ | ❌ | https://en.wikipedia.org/wiki/E.164 | +------------------------+---------------+------------+-----------------------------------------------------------------+ | ``"INTERNATIONAL"`` | ✓ | ✓ | https://en.wikipedia.org/wiki/E.123#Telephone_number | +------------------------+---------------+------------+-----------------------------------------------------------------+ | ``"RFC3966"`` | ✓ | ✓ | https://www.rfc-editor.org/rfc/rfc3966.html | +------------------------+---------------+------------+-----------------------------------------------------------------+ | ``"NATIONAL"`` | ❌ | ✓ | **DISCOURAGED**, requires :setting:`PHONENUMBER_DEFAULT_REGION` | +------------------------+---------------+------------+-----------------------------------------------------------------+ .. warning:: By default, the library uses `E.164, the international public telecommunication numbering plan `_, which **does not support phone numbers extensions**. Set **both** :setting:`PHONENUMBER_DB_FORMAT` and :setting:`PHONENUMBER_DEFAULT_FORMAT` to an extension-compatible format to handle phone numbers extensions. .. setting:: PHONENUMBER_DB_FORMAT ``PHONENUMBER_DB_FORMAT`` ------------------------- Store phone numbers strings in the specified format in the database. Default: ``"E164"``. See :ref:`settings-format-choices`. .. warning:: **Data loss may occur when changing the DB format.** Phone numbers stored in the database are parsed every time they are loaded from the database. When switching from a format that can represent extensions to a format that cannot, the **extension information is definitely lost**. When using :setting:`PHONENUMBER_DB_FORMAT`\ ``="NATIONAL"``, changing the :setting:`PHONENUMBER_DEFAULT_REGION` will cause phone numbers stored in the database to be interpreted differently, resulting in data corruption. .. setting:: PHONENUMBER_DEFAULT_FORMAT ``PHONENUMBER_DEFAULT_FORMAT`` ------------------------------ String formatting of phone numbers. Default: ``"E164"``. See :ref:`settings-format-choices`. .. setting:: PHONENUMBER_DEFAULT_REGION ``PHONENUMBER_DEFAULT_REGION`` ------------------------------ `ISO-3166-1 `_ two-letter country code indicating how to interpret regional phone numbers. Default: ``None``.