Python 如何在django中验证电话号码?

Python 如何在django中验证电话号码?,python,django,validation,phone-number,Python,Django,Validation,Phone Number,我目前正在使用phonenumbers包作为django的UserCreationForm的电话号码字段的验证方法。在我当前的代码中,我使用get方法从字段中检索电话号码,然后进行验证。如果输入的号码不存在,则会弹出一个表单错误,并说明该号码不是某个国家的格式(在本例中,我使用的是singapore)。请告诉我应该对我的当前代码进行哪些更改 我尝试使用“from phonenumber_field.formfields import PhoneNumberField”进行电话号码验证,它验证了我

我目前正在使用phonenumbers包作为django的UserCreationForm的电话号码字段的验证方法。在我当前的代码中,我使用get方法从字段中检索电话号码,然后进行验证。如果输入的号码不存在,则会弹出一个表单错误,并说明该号码不是某个国家的格式(在本例中,我使用的是singapore)。请告诉我应该对我的当前代码进行哪些更改

我尝试使用“from phonenumber_field.formfields import PhoneNumberField”进行电话号码验证,它验证了我输入的号码,唯一的问题是用户必须键入他们的国家代码,我无法输入。我只使用电话号码包,这样用户就不必输入国家代码

/* 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})

我希望输出能够验证电话字段中输入的电话号码,不带国家/地区代码,只有8位数字,如果该号码不存在,则会引发错误。

我认为您的验证是正确的,但您有两件事做错了:

  • 将方法重命名为
    clean\u phone\u number()
    ,而不是
    clean\u phone
    。该字段是
    phone\u number
    而不是
    phone
  • 将该字段改为
    CharField
    ,而不是
    IntegerField
    (对许多用户来说限制太多),并
    返回z.national\u number
    而不是
    phone\u number
    ,这样在保存之前它会返回正确清理过的号码。或者任何你想存储的格式

我对这些软件包并不完全熟悉,但在查看了它们背后的回购代码后,您似乎可以在
PhoneNumberField
上设置
region
属性,并继续继承其所有验证功能,以防用户需要在其区域中键入

像这样的


类UserRegisterPerform(UserCreationForm):
email=forms.EmailField()
#这不适合你的情况吗?
电话号码=电话号码字段(region=“SG”)
类元:
模型=用户
字段=[“用户名”、“电子邮件”、“电话号码”]
def clean_电子邮件(自我):
email=self.cleanned_data.get(“email”)
如果未验证电子邮件(电子邮件,verify=True):
raise forms.ValidationError(“无效电子邮件”)
返回电子邮件

您需要修改您的
是否有效\u编号(z)
或您的
z
变量,方法是在验证前将代码添加到编号前面。提供您的
is\u valid\u number(z)
函数以帮助您获得更多帮助。您应该调用您的方法
clean\u phone\u number()
,否则它将不会被调用。除此之外,它应该是有效的,我已经尝试了你的代码,对我有效。我也会将你的输入字段设置为
CharField
,而不是
IntegerField
,因为人们倾向于在电话号码中添加空格或破折号。您的验证将负责清理号码:不要
返回电话号码
,而是
返回z.national\u号码
。谢谢您为我工作,有一个问题,我可以将返回语句改为“return phonenumbers.format\u number(z,phonenumbers.PhoneNumberFormat.E164)”吗。最好将数字转换为E164格式,而不是本地格式。region属性是否仅适用于一个特定区域或所有区域?比如说,除了SG之外,美国也可以输入他们的数字。它只适用于您指定的地区。主要是因为在实例化
PhoneNumberField
期间,有一个
validate\u region
函数正在运行。如果您传递的区域与其预定义列表不匹配,则会引发ValueError,但它将允许
。但如果没有传递区域,则会自动尝试解析需要国家代码的号码,否则该号码将被视为无效。它需要国家代码,这样它才能知道哪个regex用于哪个地区。关于它如何决定这一点,它有点更深入、更复杂,但这是我所了解的。这里有一个链接,指向存储每个地区的所有电话号码元数据的位置。基本上为每个区域存储模式等,并且看起来是在模块中动态加载的。