As per jpotter6, you can do something like the following in your models as well:
File models.py:
from django.core.validators import RegexValidatorclass PhoneModel(models.Model):...phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")phone_number = models.CharField(validators=[phone_regex], max_length=17, blank=True) # Validators should be a list
Use django-phonenumber-field:
pip install django-phonenumber-field
Use a CharField
for the phone field in the model and the localflavor
app for form validation:
https://docs.djangoproject.com/en/1.7/topics/localflavor/
As of 2021-12-07, it looks like LocalFlavor is no longer part of Django.
Validation is easy. Text them a little code to type in.
A CharField is a great way to store it. I wouldn't worry too much about canonicalizing phone numbers.
This solution worked for me:
First install django-phone-field. Command:
pip install django-phone-field
Then in file models.py:
from phone_field import PhoneField...class Client(models.Model):...phone_number = PhoneField(blank=True, help_text='Contact phone number')
And in file settings.py:
INSTALLED_APPS = [...,'phone_field']
It looks like this in the end:
First, install "django-phonenumber-field" package with the command below:
pip install django-phonenumber-field[phonenumbers]
Then, set "phonenumber_field" to INSTALLED_APPS in "settings.py":
# "settings.py"INSTALLED_APPS = [..."phonenumber_field",...]
Then, set a field with "PhoneNumberField()" in "models.py":
# "models.py"from django.db import modelsfrom phonenumber_field.modelfields import PhoneNumberFieldclass Contact(models.Model):phone = PhoneNumberField()
Then, register "Contact" in "admin.py":
# "admin.py"from django.contrib import adminfrom .models import Contact@admin.register(Contact)class ContactAdmin(admin.ModelAdmin):pass
Then, run the command below:
python manage.py makemigrations && python manage.py migrate
Now, the field for a phone number is created as shown below:
In addition, assign the widget "PhoneNumberPrefixWidget()" to the field in a custom form and assign the custom form to the admin as shown below:
# "admin.py"from django.contrib import adminfrom .models import Contactfrom django import formsfrom phonenumber_field.widgets import PhoneNumberPrefixWidgetclass ContactForm(forms.ModelForm):class Meta:widgets = {'phone': PhoneNumberPrefixWidget(),}@admin.register(Contact)class ContactAdmin(admin.ModelAdmin):form = ContactForm
Now, with country codes, the field for a phone number is created
And, you can set an initial country code like initial='US' to "PhoneNumberPrefixWidget()" as shown below. *Initial country code must be uppercase:
# "admin.py"from django.contrib import adminfrom .models import Contactfrom django import formsfrom phonenumber_field.widgets import PhoneNumberPrefixWidgetclass ContactForm(forms.ModelForm):class Meta:widgets = { # Here'phone': PhoneNumberPrefixWidget(initial='US'),}@admin.register(Contact)class ContactAdmin(admin.ModelAdmin):form = ContactForm
Now, with the initial country code "US" selected, the field for a phone number is created:
You can also set an initial country code with "PHONENUMBER_DEFAULT_REGION" in "settings.py" as shown below but I recommand to set an initial country code with initial='US' to "PhoneNumberPrefixWidget()" as I've done above because using "PHONENUMBER_DEFAULT_REGION" sometimes doesn't display saved phone numbers in Django Admin:
# "settings.py"PHONENUMBER_DEFAULT_REGION = "US"
Others mentioned django-phonenumber-field
. To get the display format how you want you need to set PHONENUMBER_DEFAULT_FORMAT
setting to "E164"
, "INTERNATIONAL"
, "NATIONAL"
, or "RFC3966"
, however you want it displayed. See the GitHub source.
It all depends on what you understand as a phone number. Phone numbers are country-specific. The localflavors packages for several countries contains their own "phone number field". So if you are OK being country-specific you should take a look at localflavor package (class us.models.PhoneNumberField
for the US case, etc.)
Otherwise you could inspect the localflavors to get the maximum length for all countries. Localflavor also has forms fields you could use in conjunction with the country code to validate the phone number.
I will describe what I use:
Validation: The string contains more than 5 digits.
Cleaning: removing all non-digit symbols and writing only numbers to the database. I'm lucky, because in my country (Russia) everybody has phone numbers with 10 digits. So I store only 10 digits in the database. If you are writing a multi-country application, then you should make a comprehensive validation.
Rendering: I write a custom template tag to render nicely it in the template. Or even render it like a picture - it is safer to prevent SMS spam.
First of all, you need to install the phone number Django package.
pip install django-phonenumber-field[phonenumbers]
Then next is to add it to the installed applications:
INSTALLED_APPS = [...'phonenumber_field',...]
This is how to use it in your model:
from phonenumber_field.modelfields import PhoneNumberFieldclass Artist(models.Model):phone_number = PhoneNumberField()
1)# Installs phonenumbers minimal metadatapip install "django-phonenumber-field[phonenumberslite]"# Installs phonenumbers extended features (e.g. geocoding)pip install "django-phonenumber-field[phonenumbers]I recommend using that pip install "django-phonenumber-field[phonenumbers]"2) models.pyfrom django.contrib.auth.models import AbstractUserfrom phonenumber_field.modelfields import PhoneNumberFieldclass CustomUser(AbstractUser):phone = PhoneNumberField(unique=True, region='IR')3) Settings.pyAUTH_USER_MODEL = 'accounts.CustomUser'4)forms.pyfrom django.contrib.auth.forms import UserCreationForm, UserChangeFormfrom django.contrib.auth import get_user_modelfrom phonenumber_field.widgets import PhoneNumberPrefixWidget# from .models import CustomUserclass CustomUserCreationForm(UserCreationForm):class Meta:model = get_user_model()widgets = {'phone': PhoneNumberPrefixWidget(),}# fields = UserCreationForm.Meta.fields +('phone',) fields = ['phone']class CustomUserChangeForm(UserChangeForm):class Meta:model = get_user_model()widgets = {'phone': PhoneNumberPrefixWidget(),}# fields = UserChangeForm.Meta.fields +('phone',) fields = ['phone']Important : Requires the Babel package be installed.5)admin.pyfrom django.contrib import adminfrom django.contrib.auth.admin import UserAdminfrom django.contrib.auth import get_user_modelfrom .forms import CustomUserCreationForm, CustomUserChangeForm@admin.register(get_user_model())class CustomUserAdmin(UserAdmin):model =get_user_model()add_form = CustomUserCreationFormform = CustomUserChangeFormlist_display = ['username','email','phone']add_fieldsets = UserAdmin.add_fieldsets +((None,{'fields':('phone',),}),)fieldsets = UserAdmin.fieldsets +((None,{'fields':('phone',),}),)# admin.site.register(get_user_model(), CustomUserAdmin)