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 extra、または軽量なメタデータパッケージを使う phonenumberslite extra のいずれかを指定してインストールします。たとえば、プロジェクトの環境で python -m pip install "django-phonenumber-field[phonenumbers]" を実行します。lite extraを使う場合は、phonenumbers を phonenumberslite に置き換えてください。これらは選択肢となるextraです。アプリケーションに必要なメタデータの範囲に応じて選んでください。このプロジェクトはGitHub上のdjango-phonenumber-fieldで保守されています。これは、GoogleのlibphonenumberをPythonに移植したpython-phonenumbersを使用します。
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にできるかを決めてください。