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


131

我这样存储电话号码model

phone_number = models.CharField(max_length=12)

用户将输入电话号码,而我将使用该电话号码。SMS Authentication此应用程序将在全球范围内使用。因此,我还需要国家代码。是CharField存储电话号码的好方法吗?而且,我该如何验证电话号码?


1
这里有一个很好的建议:stackoverflow.com/a/1245990/207791
Victor Sergienko 2015年

Answers:


283

实际上,您可能会研究国际标准格式E.164例如Twilio推荐的格式(该服务具有通过REST请求发送SMS或电话的服务和API)。

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

1.通过PhoneNumberField打电话

您可以使用phonenumber_field库。它是Google的libphonenumber库的端口,该库为Android的电话号码处理提供支持 https://github.com/stefanfoulis/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()

从对象字段获取电话作为字符串:

    client.phone.as_e164 

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

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

2.通过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 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

19
展示如何在模型上执行此操作可能也很有价值。phone_regex = RegexValidator(regex = r'^ \ +?1?\ d {9,15} $',message =“电话号码必须以以下格式输入:'+ 999999999'。最多15位数字。”)phone_number = models.CharField(validators = phone_regex,blank = True)
jpotts18年

12
不要忘记在模型中添加'max_length =15'。CharField–
Esteban

4
@Esteban-max_length = 16(开始时有一个可选的+)
dhackner 2015年

3
@erewok-我不相信您在正则表达式中需要'1'。E.164最多允许15位数字,包括国家/地区代码。
dhackner,2015年

1
事实上,E.164不包含任何国际长途前缀,只有国家码,然后按实际数量,也是一个E.164号码的最小长度似乎是8这样的正则表达式应该是'^\+\d{8,15}$',然后max_length=16CharField
Maxime R.

48

使用django-phonenumber-field:https : //github.com/stefanfoulis/django-phonenumber-field

pip install django-phonenumber-field

1
不要忘记添加区域。如果没有PHONENUMBER_DEFAULT_REGION = 'US'设置,则不允许您输入美国用户会识别为电话号码的任何内容。即使这样,此程序包也不会输出为类似于电话号码的内容。。。我确定还有一个我还没有找到的设置!
Drigan

7
注意:这个包裹很大。超过40MB。其中33MB是地理数据。
Forethinker

1
注意到@Forethinker的评论,更轻巧的替代方法是github.com/VeryApt/django-phone-field,通过pip install django-phone-field
SMX

@Forethinker然后我们可以使用pip install django-phonenumber-field[phonenumberslite]不包含地理编码,运营商和时区元数据的“精简版”
heyjr,


3

验证很容易,向他们发送一些代码以进行输入。CharField是存储它的好方法。我不必担心将电话号码规范化。


1

这完全取决于您对电话号码的理解。电话号码是特定国家/地区的。多个国家/地区的本地风味软件包中包含自己的“电话号码字段”。因此,如果您确定要针对特定​​国家/地区,则应查看localflavor包装(class us.models.PhoneNumberField针对美国情况等)

否则,您可以检查当地风味以获取所有国家/地区的最大长度。Localflavor还具有表单字段,您可以将其与国家/地区代码一起使用以验证电话号码。


嗯,是的,我在进行研究时发现。您能举一个如何在表格中使用它的例子吗?
pynovice

1

我将描述我所使用的:

验证:字符串包含5个以上的数字。

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

渲染:我编写了自定义模板标签,以在模板中很好地渲染它。甚至将其渲染为图片-防止垃圾短信更加安全。


0

其他人提到django-phonenumber-field。为了让你想怎么你需要设置显示格式PHONENUMBER_DEFAULT_FORMAT设置"E164""INTERNATIONAL""NATIONAL",或"RFC3966",但是你想让它显示出来。参见GitHub源码

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.