How to validate phone number in django?
Your validation looks correct to me, but you're doing two things wrong:
- Rename the method to
clean_phone_number()
instead ofclean_phone
. The field isphone_number
notphone
. - Change the field to a
CharField
instead ofIntegerField
(too restrictive for many users) andreturn z.national_number
instead ofphone_number
, that way it's returning the correctly cleaned number before saving. Or whatever format you want to store it in.
Jackson_Stake
Updated on June 04, 2022Comments
-
Jackson_Stake almost 2 years
I'm currently using phonenumbers package as a validation method to my django's UserCreationForm for its phone number field. In my current code I am using a get method to retrieve the phone number from its field and then do the validation. If the entered number does not exists, a form error is supposed to pop up and state that the number is not in a country's format (in this case i'm using singapore). Please tell me what changes should be made to my current code.
I've tried using "from phonenumber_field.formfields import PhoneNumberField" for the phone number validation and it validates the number I've entered, the only problem is that the users will have to type their country code and I cannot have that. I'm using just the phonenumbers package so that users will not have to enter the country code.
/* forms.py */ import phonenumbers from django import forms from django.contrib.auth.models import User from django.contrib.auth.forms import UserCreationForm from validate_email import validate_email from phonenumber_field.formfields import PhoneNumberField class UserRegisterForm(UserCreationForm): email = forms.EmailField() # phone_number = PhoneNumberField() phone_number = forms.IntegerField(required=True) class Meta: model = User fields = ['username', 'email', 'phone_number'] def clean_email(self): email = self.cleaned_data.get("email") if not validate_email(email, verify=True): raise forms.ValidationError("Invalid email") return email def clean_phone(self): phone_number = self.cleaned_data.get("phone_number") z = phonenumbers.parse(phone_number, "SG") if not phonenumbers.is_valid_number(z): raise forms.ValidationError("Number not in SG format") return phone_number /* views.py */ from django.shortcuts import render, redirect from django.contrib import messages from .forms import UserRegisterForm def register(request): if request.method == 'POST': form = UserRegisterForm(request.POST) if form.is_valid(): # user = form.save() # phone_number = form.cleaned_data['phone'] # do something with phone number?? user = form.save() user.refresh_from_db() phone = form.cleaned_data.get('phone_number') user.Meta.phone_number = phone user.save() username = form.cleaned_data.get('username') messages.success(request, f'Account created for {username}!') return redirect('blog-home') else: form = UserRegisterForm() return render(request, 'users/register.html', {'form': form})
I expect the output to validate the entered phone number in the phone field without its country code and only 8 digits and raise an error if that number does not exist.
-
Kostas Charitidis over 4 yearsYou need to make modifications eithe to your
is_valid_number(z)
or to yourz
variable by adding the code yourself in front of the number before validation. Provide youris_valid_number(z)
function to help you more. -
dirkgroten over 4 yearsYou should call your method
clean_phone_number()
otherwise it won't be called. Apart from that, it should work, I've tried your code, works for me. -
dirkgroten over 4 yearsI would also make your input field a
CharField
instead ofIntegerField
because people tend to add spaces or dashes in phone numbers. Your validation will take care of cleaning the number: don'treturn phone_number
, butreturn z.national_number
instead.
-
-
Jackson_Stake over 4 yearsThank you its working for me, one question tho, can i write the return sentence to "return phonenumbers.format_number(z, phonenumbers.PhoneNumberFormat.E164)" instead. It might be better to convert the number to E164 format instead of local format.
-
Jackson_Stake over 4 yearsDoes the region attribute only work for one specific region or all regions? Lets say other than SG, US can type in their numbers as well
-
Chris H over 4 yearsIt will only work for the region you specify. Mainly because during the instantiation of the
PhoneNumberField
there is avalidate_region
function that is run. It will raise a ValueError if you pass a region that does not match its predefined list, though it will allowNone
. But not passing a region will automatically try to parse the number which does require a country code otherwise the number is considered invalid. It needs that country code so that it knows which regex to use for which region. -
Chris H over 4 yearsIt goes quite a bit deeper and more complex on how it decides that but this is about as far as I looked into it. Here is a link to where all the phone number metadata for each region is stored. Basically stores patterns and such for each region and it looks to be dynamically loaded in within the module. github.com/daviddrysdale/python-phonenumbers/tree/dev/python/…