The PhoneNumber wrapper

class phonenumber_field.phonenumber.PhoneNumber

A extended version of phonenumbers.PhoneNumber that provides some neat and more pythonic, easy to access methods. This makes using a PhoneNumber instance much easier, especially in templates and such.

classmethod from_string(phone_number, region=None) Self
Parameters:
  • phone_number (str) – parse this str as a phone number.

  • region (str) – 2-letter country code as defined in ISO 3166-1. When not supplied, defaults to PHONENUMBER_DEFAULT_REGION

is_valid()

Whether the number supplied is actually valid.

Returns:

True when the phone number is valid.

Return type:

bool

property as_international
property as_national
property as_e164
property as_rfc3966

Usage

>>> 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 PhoneNumberField model field allows storing PhoneNumbers in the database, based on a CharField.

The phone number format used by the database is controlled with PHONENUMBER_DB_FORMAT. When no region is specified, a phone number in the "NATIONAL" format will be assumed to be from the PHONENUMBER_DEFAULT_REGION.

class phonenumber_field.modelfields.PhoneNumberField(*args, region=None, **kwargs)
__init__(*args, region=None, **kwargs)
Parameters:
  • region (str) – 2-letter country code as defined in ISO 3166-1. When not supplied, defaults to PHONENUMBER_DEFAULT_REGION

  • max_length (int) – The maximum length of the underlying char field.

Usage

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

PhoneNumberField

The PhoneNumberField form field to validate PhoneNumber, based on a CharField.

class phonenumber_field.formfields.PhoneNumberField(*args, region=None, widget=None, **kwargs)
__init__(*args, region=None, widget=None, **kwargs)
Parameters:

Usage

>>> from django import forms
>>> from phonenumber_field.formfields import PhoneNumberField

>>> class PhoneForm(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())
<div>
 <label for="id_number">
  Number:
 </label>
 <input id="id_number" name="number" required="" type="tel" value="(604) 401-1234"/>
</div>

# Handling errors
>>> form = PhoneForm({"number": "invalid"})
>>> form.is_valid()
False
>>> print_html(form.as_div())
<div>
 <label for="id_number">
  Number:
 </label>
 <ul class="errorlist">
  <li>
   Enter a valid phone number (e.g. (506) 234-5678) or a number with an international call prefix.
  </li>
 </ul>
 <input aria-invalid="true" id="id_number" name="number" required="" type="tel" value="invalid"/>
</div>

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.

SplitPhoneNumberField

A MultiValueField that offers:

  • a <select > element to choose the region, and

  • an <input type="tel" > to enter the phone number.

This widget uses an example phone number from the selected region for the invalid key in error_messages, when the region choice is valid.

To customize the dynamic message, use phonenumber_field.formfields.SplitPhoneNumberField.invalid_error_message().

Important

Requires the Babel package.

class phonenumber_field.formfields.SplitPhoneNumberField(*, initial=None, region=None, widget=None, **kwargs)
__init__(*, initial=None, region=None, widget=None, **kwargs)
Parameters:
invalid_error_message()

Hook to customize error_messages["invalid"] for a given region.

Include the example number in the message with the {example_number} placeholder.

Usage

>>> from django import forms
>>> from phonenumber_field.formfields import SplitPhoneNumberField

>>> class PhoneForm(forms.Form):
...     number = SplitPhoneNumberField()
...

>>> form = PhoneForm()
>>> print_html_compact(form.as_div())
<div>
 <fieldset>
  <legend>
   Number:
  </legend>
  <select id="id_number_0" name="number_0" required="">
   <option selected="" value="">
    ---------
   </option>
   <option value="AF">
    Afghanistan +93
   </option>
   <option value="AL">
    Albania +355
   </option>
   ...
   <option value="AX">
    Åland Islands +358
   </option>
  </select>
  <input id="id_number_1" name="number_1" required="" type="tel"/>
 </fieldset>
</div>

# Limiting country choices.
>>> class DemoSplitPhoneNumberField(SplitPhoneNumberField):
...     def prefix_field(self):
...         return forms.ChoiceField(choices=[
...             ("", "---------"),
...             ("CA", "Canada"),
...             ("FR", "France"),
...         ])
...
>>> class LimitedCountryPhoneForm(forms.Form):
...     number = DemoSplitPhoneNumberField()
...
>>> form = LimitedCountryPhoneForm()
>>> print_html(form.as_div())
<div>
 <fieldset>
  <legend>
   Number:
  </legend>
  <select id="id_number_0" name="number_0" required="">
   <option selected="" value="">
    ---------
   </option>
   <option value="CA">
    Canada
   </option>
   <option value="FR">
    France
   </option>
  </select>
  <input id="id_number_1" name="number_1" required="" type="tel"/>
 </fieldset>
</div>

# Pre-selecting a country.
>>> class FrenchPhoneForm(forms.Form):
...     number = DemoSplitPhoneNumberField(region="FR")
...

>>> form = FrenchPhoneForm()
>>> print_html(form.as_div())
<div>
 <fieldset>
  <legend>
   Number:
  </legend>
  <select id="id_number_0" name="number_0" required="">
   <option value="">
    ---------
   </option>
   <option value="CA">
    Canada
   </option>
   <option selected="" value="FR">
    France
   </option>
  </select>
  <input id="id_number_1" name="number_1" required="" type="tel"/>
 </fieldset>
</div>

Widgets

RegionalPhoneNumberWidget

Default widget for PhoneNumberField.

  • input_type: tel

  • Renders as <input type="tel" >

Important

The region should be specified (either per field using the region keyword argument, or with the PHONENUMBER_DEFAULT_REGION setting) in order to know which national number format to recognize.

class phonenumber_field.widgets.RegionalPhoneNumberWidget(region=None, attrs=None)

A Widget that prefers displaying numbers in the national format, and falls back to PHONENUMBER_DEFAULT_FORMAT for international numbers.

__init__(region=None, attrs=None)
Parameters:

Usage

>>> from django import forms
>>> from phonenumber_field.formfields import PhoneNumberField

>>> class CanadianPhoneForm(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())
<div>
 <label for="id_number">
  Number:
 </label>
 <input id="id_number" name="number" required="" type="tel" value="(604) 401-1234"/>
</div>

# Using E164 for an international number.
>>> french_number = "+33612345678"
>>> form = CanadianPhoneForm({"number": french_number})
>>> print_html(form.as_div())
<div>
 <label for="id_number">
  Number:
 </label>
 <input id="id_number" name="number" required="" type="tel" value="+33612345678"/>
</div>

PhoneNumberPrefixWidget

class phonenumber_field.widgets.PhoneNumberPrefixWidget(widgets, attrs=None)

Companion widget of SplitPhoneNumberField.

Serializer field

The PhoneNumberField serializer field, based on the CharField.

The serialization format is controlled by the PHONENUMBER_DEFAULT_FORMAT.

class phonenumber_field.serializerfields.PhoneNumberField(*args, **kwargs)
__init__(*args, region=None, **kwargs)
Parameters:

region (str) – 2-letter country code as defined in ISO 3166-1. When not supplied, defaults to PHONENUMBER_DEFAULT_REGION

Usage

>>> 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:

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.

phonenumber_field.validators.validate_international_phonenumber(value)

code: "invalid"

Settings

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 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 PHONENUMBER_DB_FORMAT and PHONENUMBER_DEFAULT_FORMAT to an extension-compatible format to handle phone numbers extensions.

PHONENUMBER_DB_FORMAT

Store phone numbers strings in the specified format in the database.

Default: "E164".

See Phone number 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 PHONENUMBER_DB_FORMAT="NATIONAL", changing the PHONENUMBER_DEFAULT_REGION will cause phone numbers stored in the database to be interpreted differently, resulting in data corruption.

PHONENUMBER_DEFAULT_FORMAT

String formatting of phone numbers.

Default: "E164".

See Phone number format choices.

PHONENUMBER_DEFAULT_REGION

ISO-3166-1 two-letter country code indicating how to interpret regional phone numbers.

Default: None.