411๐
You might actually look into the internationally standardized format E.164, recommended by Twilio for example (who have a service and an API for sending SMS or phone-calls via REST requests).
This is likely to be the most universal way to store phone numbers, in particular if you have international numbers work with.
-
Phone by PhoneNumberField
You can use the
phonenumber_field
library. It is a port of Googleโs libphonenumber library, which powers Androidโs phone number handling. See django-phonenumber-field.In the model:
from phonenumber_field.modelfields import PhoneNumberField class Client(models.Model, Importable): phone = PhoneNumberField(null=False, blank=False, unique=True)
In the form:
from phonenumber_field.formfields import PhoneNumberField class ClientForm(forms.Form): phone = PhoneNumberField()
Get the phone as a string from an object field:
client.phone.as_e164
Normalize the phone string (for tests and other staff):
from phonenumber_field.phonenumber import PhoneNumber phone = PhoneNumber.from_string(phone_number=raw_phone, region='RU').as_e164
-
Phone by regexp
One note for your model: E.164 numbers have a maximum character length of 15.
To validate, you can employ some combination of formatting and then attempting to contact the number immediately to verify.
I believe I used something like the following in my django project:
class ReceiverForm(forms.ModelForm): phone_number = forms.RegexField(regex=r'^\+?1?\d{9,15}$', error_message = ("Phone number must be entered in the format: '+999999999'. Up to 15 digits is allowed."))
As per jpotter6, you can do something like the following in your models as well:
File models.py:
from django.core.validators import RegexValidator
class 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
- [Django]-How to implement FirebaseDB with a Django Web Application
- [Django]-">", "<", ">=" and "<=" don't work with "filter()" in Django
- [Django]-Django โ Render the <label> of a single form field
9๐
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.
- [Django]-405 "Method POST is not allowed" in Django REST framework
- [Django]-Django-Forms with json fields
- [Django]-Using JSON in django template
8๐
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.
- [Django]-Custom django admin templates not working
- [Django]-(13: Permission denied) while connecting to upstream:[nginx]
- [Django]-Login Page by using django forms
8๐
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:
- [Django]-What is the difference between cached_property in Django vs. Python's functools?
- [Django]-Django auto_now and auto_now_add
- [Django]-How can I access environment variables directly in a Django template?
8๐
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 models
from phonenumber_field.modelfields import PhoneNumberField
class Contact(models.Model):
phone = PhoneNumberField()
Then, register "Contact" in "admin.py":
# "admin.py"
from django.contrib import admin
from .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 admin
from .models import Contact
from django import forms
from phonenumber_field.widgets import PhoneNumberPrefixWidget
class 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 admin
from .models import Contact
from django import forms
from phonenumber_field.widgets import PhoneNumberPrefixWidget
class 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"
- [Django]-Unittest Django: Mock external API, what is proper way?
- [Django]-Do django db_index migrations run concurrently?
- [Django]-Django โ how to visualize signals and save overrides?
3๐
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.
- [Django]-How to query Case-insensitive data in Django ORM?
- [Django]-FileUploadParser doesn't get the file name
- [Django]-Django: Use of DATE_FORMAT, DATETIME_FORMAT, TIME_FORMAT in settings.py?
1๐
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.
- [Django]-How to get the domain name of my site within a Django template?
- [Django]-Django development IDE
- [Django]-Django 1.5 custom User model error. "Manager isn't available; User has been swapped"
1๐
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.
- [Django]-Python Socket.IO client for sending broadcast messages to TornadIO2 server
- [Django]-How to 'bulk update' with Django?
- [Django]-How to select a record and update it, with a single queryset in Django?
1๐
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 PhoneNumberField
class Artist(models.Model):
phone_number = PhoneNumberField()
- [Django]-Running Django with FastCGI or with mod_python
- [Django]-Django values_list vs values
- [Django]-Django: how to do calculation inside the template html page?
1๐
1)
# Installs phonenumbers minimal metadata
pip 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.py
from django.contrib.auth.models import AbstractUser
from phonenumber_field.modelfields import PhoneNumberField
class CustomUser(AbstractUser):
phone = PhoneNumberField(unique=True, region='IR')
3) Settings.py
AUTH_USER_MODEL = 'accounts.CustomUser'
4)forms.py
from django.contrib.auth.forms import UserCreationForm, UserChangeForm
from django.contrib.auth import get_user_model
from phonenumber_field.widgets import PhoneNumberPrefixWidget
# from .models import CustomUser
class 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.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth import get_user_model
from .forms import CustomUserCreationForm, CustomUserChangeForm
@admin.register(get_user_model())
class CustomUserAdmin(UserAdmin):
model =get_user_model()
add_form = CustomUserCreationForm
form = CustomUserChangeForm
list_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)
- [Django]-Folder Structure for Python Django-REST-framework and Angularjs
- [Django]-Why there are two process when i run python manage.py runserver
- [Django]-In a django model custom save() method, how should you identify a new object?