Apa cara terbaik untuk menyimpan nomor Telepon dalam model Django

131

Saya menyimpan nomor telepon modelseperti ini:

phone_number = models.CharField(max_length=12)

Pengguna akan memasukkan nomor telepon dan saya akan menggunakan nomor telepon untuk SMS AuthenticationAplikasi ini akan digunakan secara global. Jadi saya juga perlu kode negara. Apakah CharFieldcara yang baik untuk menyimpan nomor telepon? Dan, bagaimana saya memvalidasi nomor telepon?

layanan pribadi
sumber
1
Ada saran bagus di sini: stackoverflow.com/a/1245990/207791
Victor Sergienko

Jawaban:

283

Anda mungkin benar-benar melihat ke dalam format standar internasional E.164 , direkomendasikan oleh Twilio misalnya (yang memiliki layanan dan API untuk mengirim SMS atau panggilan telepon melalui permintaan REST).

Ini kemungkinan merupakan cara paling universal untuk menyimpan nomor telepon, khususnya jika Anda memiliki nomor internasional.

1. Telepon dengan PhoneNumberField

Anda bisa menggunakan phonenumber_fieldperpustakaan. Ini adalah port dari perpustakaan libphonenumber Google, yang mendukung penanganan nomor telepon Android https://github.com/stefanfoulis/django-phonenumber-field

Dalam model:

from phonenumber_field.modelfields import PhoneNumberField

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

Dalam bentuk:

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

Dapatkan ponsel sebagai string dari bidang objek:

    client.phone.as_e164 

Normolisasi string telepon (untuk tes dan staf lain):

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

2. Telepon dengan regexp

Satu catatan untuk model Anda: angka E.164 memiliki panjang karakter maks 15.

Untuk memvalidasi, Anda dapat menggunakan beberapa kombinasi pemformatan dan kemudian mencoba menghubungi nomor tersebut segera untuk memverifikasi.

Saya percaya saya menggunakan sesuatu seperti berikut pada proyek Django saya:

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

EDIT

Tampaknya pos ini bermanfaat bagi sebagian orang, dan tampaknya layak untuk mengintegrasikan komentar di bawah ini ke dalam jawaban yang lebih lengkap. Sesuai jpotter6 , Anda dapat melakukan sesuatu seperti yang berikut pada model Anda juga:

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
erewok
sumber
19
Mungkin berharga untuk menunjukkan bagaimana melakukan ini pada model juga. phone_regex = RegexValidator (regex = r '^ \ +? 1? \ d {9,15} $', message = "Nomor telepon harus dimasukkan dalam format: '+999999999'. Hingga 15 digit diizinkan.") phone_number = models.CharField (validator = phone_regex, blank = True)
jpotts18
12
Jangan lupa untuk menambahkan 'max_length = 15' ke models.CharField
Esteban
4
@Esteban - max_length = 16 (ada + opsional di awal)
dhackner
3
@ erewok - Saya tidak percaya Anda ingin '1' di regex Anda. E.164 memungkinkan hingga 15 digit, termasuk kode negara.
dhackner
1
Memang, E.164 tidak termasuk awalan panggilan internasional, hanya kode negara diikuti oleh nomor aktual, juga panjang minimum nomor E.164 tampaknya menjadi 8 sehingga regex harus '^\+\d{8,15}$'dan kemudian max_length=16untuk CharField.
Maxime R.
48

Gunakan django-phonenumber-field: https://github.com/stefanfoulis/django-phonenumber-field

pip install django-phonenumber-field
rgenito
sumber
1
Jangan lupa menambahkan wilayah. Tanpa PHONENUMBER_DEFAULT_REGION = 'US'dalam pengaturan itu tidak akan memungkinkan Anda untuk memasukkan apa pun yang akan dikenali oleh pengguna dari Amerika Serikat sebagai nomor telepon. Meski begitu, paket ini tidak akan menampilkan sesuatu yang terlihat seperti nomor telepon. . . Saya yakin ada pengaturan yang belum saya temukan!
Drigan
7
Catatan: paket ini sangat besar. Lebih dari 40MB. 33MB itu adalah geodata.
Forethinker
1
Memperhatikan komentar @Forethinker , alternatif yang jauh lebih ringan adalah github.com/VeryApt/django-phone-field , viapip install django-phone-field
SMX
@Forethinker maka kita dapat menggunakan versi "lite" pip install django-phonenumber-field[phonenumberslite]yang tidak termasuk geocoding, carrier dan metadata zona waktu
heyjr
3

Validasi mudah, teks mereka sedikit kode untuk mengetik. CharField adalah cara yang bagus untuk menyimpannya. Saya tidak akan terlalu khawatir tentang kanonikisasi nomor telepon.

U2EF1
sumber
1

Itu semua tergantung pada apa yang Anda pahami sebagai nomor telepon. Nomor telepon spesifik negara. Paket rasa lokal untuk beberapa negara berisi "bidang nomor telepon" mereka sendiri. Jadi, jika Anda setuju dengan negara spesifik Anda harus melihat pada paket rasa lokal (class us.models.PhoneNumberField untuk kasus AS, dll.)

Kalau tidak, Anda bisa memeriksa rasa lokal untuk mendapatkan panjang maksimal untuk semua negara. Localflavor juga memiliki bidang formulir yang dapat Anda gunakan bersama dengan kode negara untuk memvalidasi nomor telepon.

esauro
sumber
Hm Ya, saya menemukan itu ketika saya melakukan penelitian. Bisakah Anda memberi contoh tentang cara menggunakannya dalam formulir.
pynovice
1

Saya akan menjelaskan apa yang saya gunakan:

Validasi: string berisi lebih dari 5 digit.

Pembersihan: menghapus semua simbol non digit, tulis hanya dalam angka db. Saya beruntung, karena di negara saya (Rusia) setiap orang memiliki nomor telepon dengan 10 digit. Jadi saya menyimpan dalam db hanya 10 buah. Jika Anda menulis aplikasi multi-negara, maka Anda harus membuat validasi komprehensif.

Rendering: Saya menulis tag templat khusus untuk membuatnya dalam templat dengan baik. Atau bahkan membuatnya seperti gambar - lebih aman untuk mencegah spam sms.

Павел Тявин
sumber
0

Lainnya disebutkan django-phonenumber-field. Untuk mendapatkan format tampilan bagaimana Anda ingin Anda perlu set PHONENUMBER_DEFAULT_FORMATpengaturan untuk "E164", "INTERNATIONAL", "NATIONAL", atau "RFC3966", namun Anda ingin ditampilkan. Lihat sumber GitHub .

GoPackGo90
sumber