在 Django 模型中存储电话号码的最好方法是什么?

我像这样在model中存储一个电话号码:

phone_number = models.CharField(max_length=12)

用户将输入一个电话号码,我将使用电话号码手机短信验证。该应用程序将被全局使用。所以我还需要国家代码。CharField是存储电话号码的好方法吗?以及,我如何验证电话号码?

219150 次浏览

这完全取决于你对电话号码的理解。电话号码是国家特有的。一些国家的本地风味包包含他们自己的“电话号码字段”。所以,如果你对特定国家的口味没问题,你应该看看当地的口味包(美国的情况是class us.models.PhoneNumberField,等等)。

否则,你可以检查当地的口味,以获得所有国家的最大长度。Localflavor还有一些表单字段,可以与国家代码一起使用来验证电话号码。

我将描述我所使用的:

验证:字符串包含超过5位数字。

清除:删除所有非数字符号,只向数据库写入数字。我很幸运,因为在我的国家(俄罗斯),每个人的电话号码都是10位数。所以我在数据库中只存储了10个数字。如果您正在编写一个多国应用程序,那么您应该进行全面验证。

渲染:我编写了一个自定义模板标记,以便在模板中很好地渲染它。甚至像图片一样渲染它-这是更安全的防止短信垃圾邮件。

验证很容易。给他们发一段代码让他们输入。

CharField是存储它的好方法。我不会太担心把电话号码规范化。

实际上,你可能会研究国际标准化格式E.164例如Twilio推荐的(它们有一个服务和API,用于通过REST请求发送短信或电话)。

这可能是存储电话号码的最通用方法,特别是如果您使用的是国际号码。

  1. Phone by PhoneNumberField

    你可以使用phonenumber_field库。它是谷歌的libphonenumber库的一个端口,该库支持Android的电话号码处理。看到django-phonenumber-field

    在模型中:

    from phonenumber_field.modelfields import PhoneNumberField
    
    
    class Client(models.Model, Importable):
    phone = PhoneNumberField(null=False, blank=False, unique=True)
    

    在表格中:

    from phonenumber_field.formfields import PhoneNumberField
    class ClientForm(forms.Form):
    phone = PhoneNumberField()
    

    从object字段中获取phone作为字符串:

    client.phone.as_e164
    

    规范化电话字符串(用于测试和其他工作人员):

    from phonenumber_field.phonenumber import PhoneNumber
    phone = PhoneNumber.from_string(phone_number=raw_phone, region='RU').as_e164
    
  2. Phone by regexp

    对于您的模型有一个注意事项:E.164数字的最大字符长度为15。

    要进行验证,可以使用某种格式组合,然后尝试立即联系该号码进行验证。

    我相信我在我的django项目中使用了如下的东西:

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

根据jpotter6,你也可以在你的模型中做如下的事情:

文件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-phonenumber-field:

pip install django-phonenumber-field

在模型中的phone字段使用CharField,在应用程序中使用localflavor进行表单验证:

https://docs.djangoproject.com/en/1.7/topics/localflavor/

从2021-12-07开始,LocalFlavor似乎不再是Django的一部分。

其他人提到django-phonenumber-field。为了得到你想要的显示格式,你需要设置PHONENUMBER_DEFAULT_FORMAT设置为"E164""INTERNATIONAL""NATIONAL",或"RFC3966",无论你想显示它。参见GitHub源

这个解决方案对我很有效:

首先安装django-phone-field。命令:

pip install django-phone-field

然后在文件models.py中:

from phone_field import PhoneField
...


class Client(models.Model):
...
phone_number = PhoneField(blank=True, help_text='Contact phone number')

在文件settings.py中:

INSTALLED_APPS = [...,
'phone_field'
]

最后是这样的:

Phone in form

首先,需要安装电话号码Django包。

pip install django-phonenumber-field[phonenumbers]

接下来是将其添加到已安装的应用程序中:

INSTALLED_APPS = [
...
'phonenumber_field',
...
]

下面是如何在你的模型中使用它:

from phonenumber_field.modelfields import PhoneNumberField


class Artist(models.Model):


phone_number = PhoneNumberField()

首先,用下面的命令安装“django-phonenumber-field"包:

pip install django-phonenumber-field[phonenumbers]

然后,在“settings.py"中将“phonenumber_field"设置为INSTALLED_APPS:

# "settings.py"


INSTALLED_APPS = [
...
"phonenumber_field",
...
]

然后,在“models.py"中设置一个带有“PhoneNumberField()“;的字段:

# "models.py"


from django.db import models
from phonenumber_field.modelfields import PhoneNumberField


class Contact(models.Model):
phone = PhoneNumberField()

然后,在“admin.py"中注册“Contact":

# "admin.py"


from django.contrib import admin
from .models import Contact


@admin.register(Contact)
class ContactAdmin(admin.ModelAdmin):
pass

然后,执行如下命令:

python manage.py makemigrations && python manage.py migrate

现在,电话号码字段被创建,如下所示:

enter image description here

此外,将小部件“PhoneNumberPrefixWidget()”;赋值给自定义表单中的字段,并将自定义表单赋值给管理员,如下所示:

# "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

现在,使用国家代码创建了电话号码字段

enter image description here

并且,您可以将初始国家代码如初始= '我们'设置为“PhoneNumberPrefixWidget()“;,如下所示。*国家代码的首字母必须大写:

# "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

现在,使用初始国家代码“US"选择创建电话号码字段:

enter image description here

你也可以在“settings.py"中使用“PHONENUMBER_DEFAULT_REGION"设置初始国家代码,如下所示,但我建议像我上面所做的那样,将初始= '我们'的初始国家代码设置为“PhoneNumberPrefixWidget()“;,因为使用“PHONENUMBER_DEFAULT_REGION"有时不会显示保存在Django管理中的电话号码:

# "settings.py"


PHONENUMBER_DEFAULT_REGION = "US"