Qual è il modo migliore per memorizzare il numero di telefono nei modelli Django


131

Sto memorizzando un numero di telefono in modelquesto modo:

phone_number = models.CharField(max_length=12)

L'utente inserisce un numero di telefono e io uso il numero di telefono per SMS AuthenticationQuesta applicazione verrebbe utilizzata a livello globale. Quindi avrei bisogno anche del prefisso internazionale. È CharFieldun buon modo per memorizzare il numero di telefono? E come posso convalidare il numero di telefono?


1
C'è un grande suggerimento qui: stackoverflow.com/a/1245990/207791
Victor Sergienko

Risposte:


283

Potresti effettivamente esaminare il formato standardizzato internazionale E.164 , raccomandato ad esempio da Twilio (che ha un servizio e un'API per inviare SMS o telefonate tramite richieste REST).

Questo è probabilmente il modo più universale per memorizzare i numeri di telefono, in particolare se si dispone di numeri internazionali.

1. Telefono via PhoneNumberField

Puoi usare la phonenumber_fieldlibreria. È la porta della libreria libphonenumber di Google, che alimenta la gestione dei numeri di telefono di Android https://github.com/stefanfoulis/django-phonenumber-field

Nel modello:

from phonenumber_field.modelfields import PhoneNumberField

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

Far sapere:

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

Ottieni telefono come stringa dal campo oggetto:

    client.phone.as_e164 

Normolizza stringa di telefono (per test e altro personale):

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

2. Telefonare con regexp

Una nota per il tuo modello: i numeri E.164 hanno una lunghezza massima di 15 caratteri.

Per convalidare, è possibile utilizzare una combinazione di formattazione e quindi tentare di contattare immediatamente il numero per verificare.

Credo di aver usato qualcosa di simile al mio progetto 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."))

MODIFICARE

Sembra che questo post sia stato utile per alcune persone, e sembra che valga la pena integrare il commento qui sotto in una risposta a tutti gli effetti. Secondo jpotter6 , puoi fare qualcosa di simile anche sui tuoi modelli:

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
Potrebbe essere utile mostrare come farlo anche su un modello. phone_regex = RegexValidator (regex = r '^ \ +? 1? \ d {9,15} $', message = "Il numero di telefono deve essere inserito nel formato: '+999999999'. Sono consentite fino a 15 cifre.") phone_number = models.CharField (validators = phone_regex, blank = True)
jpotts18

12
Non dimenticare di aggiungere "max_length = 15" ai modelli. CharField
Esteban

4
@Esteban - max_length = 16 (c'è un + opzionale all'inizio)
dhackner

3
@erewok - Non credo che tu voglia l'1 nella tua regex. E.164 consente fino a 15 cifre, incluso il prefisso internazionale.
Dhackner,

1
In effetti, E.164 non include alcun prefisso di chiamata internazionale, solo il prefisso internazionale seguito dal numero effettivo, anche la lunghezza minima di un numero E.164 sembra essere 8, quindi il regex dovrebbe essere '^\+\d{8,15}$'e quindi max_length=16per il CharField.
Maxime R.

48

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

pip install django-phonenumber-field

1
Non dimenticare di aggiungere la regione. Senza PHONENUMBER_DEFAULT_REGION = 'US'le impostazioni non ti consentirà di inserire qualsiasi cosa gli utenti degli Stati Uniti riconoscano come numero di telefono. Anche allora, questo pacchetto non verrà emesso come qualcosa che assomiglia a un numero di telefono. . . Sono sicuro che c'è un'impostazione che non ho ancora trovato!
Drigan,

7
Nota: questo pacchetto è molto grande. Oltre 40 MB. 33 MB di esso sono geodati.
Pensatore

1
Notando il commento di @Forethinker, un'alternativa molto più leggera è github.com/VeryApt/django-phone-field , viapip install django-phone-field
SMX

@Forethinker allora possiamo usare la versione "lite" pip install django-phonenumber-field[phonenumberslite]che non include i metadati di geocodifica, vettore e fuso orario
heyjr


3

La convalida è semplice, scrivi loro un piccolo codice per digitare. Un CharField è un ottimo modo per memorizzarlo. Non mi preoccuperei troppo di canonicalizzare i numeri di telefono.


1

Tutto dipende da ciò che intendi come numero di telefono. I numeri di telefono sono specifici del Paese. I pacchetti localflavors per diversi paesi contengono il proprio "campo del numero di telefono". Quindi, se stai bene essere specifico per un paese, dovresti dare un'occhiata al pacchetto localflavor (class us.models.PhoneNumberField per il caso negli Stati Uniti, ecc.)

Altrimenti potresti ispezionare i sapori locali per ottenere la massima lunghezza per tutti i paesi. Localflavor ha anche campi di moduli che è possibile utilizzare in combinazione con il prefisso internazionale per convalidare il numero di telefono.


Sì, l'ho scoperto mentre facevo una ricerca. Puoi fare un esempio su come usarlo in un modulo.
pynovice,

1

Descriverò ciò che uso:

Convalida: la stringa contiene più di 5 cifre.

Pulizia: rimozione di tutti i simboli non numerici, scrivere solo in numeri db. Sono fortunato, perché nel mio paese (Russia) tutti hanno numeri di telefono con 10 cifre. Quindi conservo in db solo 10 diits. Se stai scrivendo una domanda per più paesi, dovresti effettuare una convalida completa.

Rendering: scrivo un tag modello personalizzato per renderlo nel modello. O addirittura renderlo come un'immagine: è più sicuro prevenire lo spam sms.


0

Altri citati django-phonenumber-field. Per ottenere il formato di visualizzazione come si vuole è necessario impostare PHONENUMBER_DEFAULT_FORMATimpostazione "E164", "INTERNATIONAL", "NATIONAL"o "RFC3966", tuttavia si desidera visualizzare. Vedi la fonte GitHub .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.