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 field

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

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

Important

Requires the Babel package be installed.

class phonenumber_field.widgets.PhoneNumberPrefixWidget(attrs=None, initial=None, country_attrs=None, country_choices=None, number_attrs=None)

A Widget that splits a phone number into fields:

  • a Select for the country (phone prefix)

  • a TextInput for local phone number

__init__(attrs=None, initial=None, country_attrs=None, country_choices=None, number_attrs=None)
Parameters:
  • attrs (dict) – See attrs

  • initial (dict) – See initial

  • country_attrs (dict) – The attrs for the country Select.

  • country_choices (list of 2-tuple, optional The first element is the value, which must match a country code recognized by the phonenumbers project. The second element is the label.) – Limit the country choices.

  • number_attrs (dict) – The attrs for the local phone number TextInput.

Usage

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

# Limiting country choices.
>>> class CanadianPhoneForm(forms.Form):
...     # RegionalPhoneNumberWidget is the default widget.
...     number = PhoneNumberField(
...         region="CA",
...         widget=PhoneNumberPrefixWidget(
...             country_choices=[
...                  ("CA", "Canada"),
...                  ("FR", "France"),
...             ],
...         ),
...     )
...

>>> form = CanadianPhoneForm({"number_0": "CA", "number_1": "6044011234"})
>>> print_html(form.as_div())
<div>
 <fieldset>
  <legend>
   Number:
  </legend>
  <select id="id_number_0" name="number_0" required="">
   <option selected="" value="CA">
    Canada
   </option>
   <option value="FR">
    France
   </option>
  </select>
  <input id="id_number_1" name="number_1" required="" type="text" value="6044011234"/>
 </fieldset>
</div>

# Pre-selecting a country.
>>> class FrenchPhoneForm(forms.Form):
...     # RegionalPhoneNumberWidget is the default widget.
...     number = PhoneNumberField(
...         region="FR",
...         widget=PhoneNumberPrefixWidget(
...             initial="FR",
...             country_choices=[
...                  ("CA", "Canada"),
...                  ("FR", "France"),
...             ],
...         ),
...     )
...

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

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
OrderedDict([('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_phone_number"

Settings

PHONENUMBER_DB_FORMAT

Store phone numbers strings in the specified format.

Default: "E164".

Choices:

  • "E164" (public international numbers),

  • "INTERNATIONAL" (international numbers, possibly with phone extensions),

  • "RFC3966" (international numbers, possibly with phone extensions),

  • "NATIONAL" (discouraged, requires PHONENUMBER_DEFAULT_REGION).

PHONENUMBER_DEFAULT_REGION

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

Default: None.

PHONENUMBER_DEFAULT_FORMAT

String formatting of phone numbers.

Default: "E164".

Choices:

  • "E164" (no support of phone extensions),

  • "INTERNATIONAL",

  • "RFC3966",

  • "NATIONAL" (discouraged, fails to represent international phone numbers).