HOWTO · Django
在 Django 中存储电话号码的最佳方法
找出在 Django 中存储电话号码的几种方法。
本页内容
在 Django 模型中存储国际电话号码时,可使用 django-phonenumber-field 及其 PhoneNumberField;它借助包含地区信息的电话号码元数据解析并验证号码。如果应用只接受范围明确、格式受限的号码,自定义 Django 验证器也可能够用。无论采用哪种方式,都应将电话号码存为文本,而不是整数:电话号码是标识符,转换为整数可能会丢掉开头的加号或前导零。
运行以下示例:
phone_number = "+1 415 555 0132"
print(phone_number)
print(type(phone_number).__name__)
+1 415 555 0132
str
此示例说明了为什么电话号码应存放在字符串字段中。它不会解析或验证号码;如果需要处理国际格式的输入,请使用下文介绍的程序包。
使用第三方 Django 应用的 PhoneNumberField 存储电话号码
安装 django-phonenumber-field 时,可以选择功能较完整的 Python 移植版扩展 phonenumbers,也可以选择元数据包较精简的扩展 phonenumberslite。例如,在项目环境中运行 python -m pip install "django-phonenumber-field[phonenumbers]"。若要使用精简版扩展,请将 phonenumbers 替换为 phonenumberslite。这两种扩展是可选方案,请根据应用所需的元数据覆盖范围进行选择。该项目由 GitHub 上的 django-phonenumber-field 维护。它使用 python-phonenumbers,这是 Google 的 libphonenumber 的 Python 移植版。
在 Django 设置中的 INSTALLED_APPS 添加 "phonenumber_field"。然后从 phonenumber_field.modelfields 导入 PhoneNumberField,并在模型中声明字段,例如:phone_number = PhoneNumberField(unique=True)。对于可选号码,可以使用 phone_number = PhoneNumberField(blank=True, null=True)。同时导入常用的 from django.db import models,并将这些声明放在模型类中。这些代码片段依赖 Django 框架,需要在已配置的 Django 项目中安装该程序包,因此不能作为独立的运行示例使用。
PhoneNumberField 使用字符串存储,并会提供电话号码对象,用于解析、验证和格式化。这些任务彼此相关,但并不相同:解析会结合地区信息解释输入内容;验证会依据编号计划元数据检查号码;规范化会生成统一的标准表示;显示格式化则会以便于阅读的形式呈现号码。如果用户可能输入本地格式的号码,请在 Django 配置中指定默认地区;缺少足够的地区信息时,无法可靠地解释此类输入。对于已有记录,可以通过模型实例访问号码,例如 person.phone_number;需要 E.164 格式时,可使用其 as_e164 属性。配置和字段详情请参阅项目文档;国际编号计划的说明请参阅 E.164。
使用验证器和 Django 模型存储电话号码
如果应用只接受有限的号码格式,而且你能明确规定其规则,可以使用 Django 的 RegexValidator 验证 CharField。例如,从 django.core.validators 导入 RegexValidator,定义 phone_number_validator = RegexValidator(regex=r"^\+?1?\d{8,15}$"),再将它传给模型字段:phone_number = models.CharField(max_length=16, validators=[phone_number_validator], unique=True)。请将这些声明放在从 django.db 导入 models 的模型类中。这是依赖 Django 的示例,并未作为独立示例运行。
该表达式只匹配一种范围有限的格式,其中美国国家代码为可选项,并限定了数字位数。它不能验证全球各地的电话号码,也不会检查号码是否已分配,而且不等同于 PhoneNumberField。只有当这些限制符合应用接受的号码范围时才使用它;否则,请采用基于程序包的方案,或根据应用的实际需求定义验证器。
E.164 最多允许 15 位数字;国际表示形式中的前导 + 是单独的字符。max_length=16 的字段可以容纳这种表示形式,但仅设置长度并不能确保符合 E.164 语法或各国的号码规则。验证器必须检查允许的前缀和数字位数;要进行更全面的国际号码验证,则需要编号计划元数据。无论使用哪种模型字段,都应根据数据模型决定号码是否必须唯一,以及字段是否可以留空或设为 null。