Was ist der beste Weg, um Telefonnummer in Django-Modellen zu speichern

131

Ich speichere eine Telefonnummer modelwie folgt:

phone_number = models.CharField(max_length=12)

Der Benutzer würde eine Telefonnummer eingeben und ich würde die Telefonnummer für verwenden. SMS AuthenticationDiese Anwendung würde global verwendet. Also würde ich auch Ländercode brauchen. Ist CharFieldeine gute Möglichkeit, Telefonnummer zu speichern? Und wie überprüfe ich die Telefonnummer?

pynovice
quelle
1
Hier gibt es einen großartigen Vorschlag: stackoverflow.com/a/1245990/207791
Victor Sergienko

Antworten:

282

Sie aussehen könnten tatsächlich in das international genormte Format E.164 , von Twilio zum Beispiel empfohlen (die für das Senden von SMS oder Telefon-Anrufen über REST - Anfragen einen Service und eine API).

Dies ist wahrscheinlich die universellste Methode zum Speichern von Telefonnummern, insbesondere wenn Sie mit internationalen Nummern arbeiten.

1. Telefon von PhoneNumberField

Sie können die phonenumber_fieldBibliothek verwenden. Es ist der Port der libphonenumber-Bibliothek von Google, die die Handhabung der Telefonnummer von Android unter https://github.com/stefanfoulis/django-phonenumber-field unterstützt

Im Modell:

from phonenumber_field.modelfields import PhoneNumberField

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

Informieren:

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

Holen Sie sich das Telefon als Zeichenfolge aus dem Objektfeld:

    client.phone.as_e164 

Telefonschnur normieren (für Tests und anderes Personal):

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

2. Telefon per Regexp

Ein Hinweis für Ihr Modell: E.164-Zahlen haben eine maximale Zeichenlänge von 15.

Zur Validierung können Sie eine Kombination aus Formatierung und anschließendem Versuch verwenden, die Nummer sofort zu kontaktieren, um dies zu überprüfen.

Ich glaube, ich habe in meinem Django-Projekt Folgendes verwendet:

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

BEARBEITEN

Es scheint, dass dieser Beitrag für einige Leute nützlich war, und es scheint sich zu lohnen, den folgenden Kommentar in eine umfassendere Antwort zu integrieren. Wie pro jpotter6 , können Sie so etwas wie die folgenden auf Ihre Modelle auch tun:

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
quelle
19
Es kann hilfreich sein, zu zeigen, wie dies auch an einem Modell funktioniert. phone_regex = RegexValidator (regex = r '^ \ +? 1? \ d {9,15} $', message = "Die Telefonnummer muss im Format '+999999999' eingegeben werden. Bis zu 15 Ziffern zulässig.") phone_number = models.CharField (validators = phone_regex, blank = True)
jpotts18
12
Vergessen Sie nicht, 'max_length = 15' zu den Modellen hinzuzufügen.CharField
Esteban
4
@Esteban - max_length = 16 (es gibt ein optionales + am Start)
Dhackner
3
@erewok - Ich glaube nicht, dass du die '1' in deiner Regex haben willst. E.164 erlaubt bis zu 15 Ziffern, einschließlich der Landesvorwahl.
Dhackner
1
In der Tat enthält E.164 keine Präfixe für internationale Anrufe, nur den Ländercode gefolgt von der tatsächlichen Nummer. Außerdem scheint die Mindestlänge einer E.164-Nummer 8 zu sein, daher sollte der reguläre Ausdruck sein '^\+\d{8,15}$'und dann max_length=16für die CharField.
Maxime R.
47

Verwenden Sie das Django-Telefonnummernfeld: https://github.com/stefanfoulis/django-phonenumber-field

pip install django-phonenumber-field
rgenito
quelle
1
Vergessen Sie nicht, die Region hinzuzufügen. Ohne PHONENUMBER_DEFAULT_REGION = 'US'in den Einstellungen können Sie nichts eingeben, was Benutzer aus den USA als Telefonnummer erkennen würden. Selbst dann wird dieses Paket nicht als etwas ausgegeben, das wie eine Telefonnummer aussieht. . . Ich bin sicher, es gibt eine Einstellung, die ich noch nicht gefunden habe!
Drigan
7
Hinweis: Dieses Paket ist sehr groß. Über 40 MB. 33 MB davon sind Geodaten.
Forethinker
1
Unter Hinweis auf @Forethinkers Kommentar ist github.com/VeryApt/django-phone-field überpip install django-phone-field
SMX
@Forethinker dann können wir die "lite" -Version verwenden, pip install django-phonenumber-field[phonenumberslite]die die Metadaten für Geokodierung, Träger und Zeitzone nicht enthält
heyjr
3

Die Validierung ist einfach. Schreiben Sie ihnen einen kleinen Code zum Eingeben. Ein CharField ist eine großartige Möglichkeit, ihn zu speichern. Ich würde mir keine Sorgen um die Kanonisierung von Telefonnummern machen.

U2EF1
quelle
1

Es hängt alles davon ab, was Sie als Telefonnummer verstehen. Telefonnummern sind länderspezifisch. Die localflavors-Pakete für mehrere Länder enthalten ein eigenes "Telefonnummernfeld". Wenn Sie also in der Lage sind, länderspezifisch zu sein, sollten Sie sich das Paket localflavor ansehen ( class us.models.PhoneNumberFieldfür US-Fälle usw.).

Andernfalls könnten Sie die lokalen Aromen überprüfen, um die maximale Länge für alle Länder zu erhalten. Localflavor verfügt auch über Formularfelder, die Sie in Verbindung mit der Landesvorwahl zur Überprüfung der Telefonnummer verwenden können.

Esauro
quelle
Hm Ja, das habe ich während meiner Recherche gefunden. Können Sie ein Beispiel für die Verwendung in einem Formular geben?
Pynovice
1

Ich werde beschreiben, was ich benutze:

Validierung: Zeichenfolge enthält mehr als 5 Ziffern.

Reinigung: Entfernen Sie alle nicht-stelligen Symbole. Schreiben Sie nur DB-Zahlen. Ich habe Glück, denn in meinem Land (Russland) hat jeder eine 10-stellige Telefonnummer. Also speichere ich in db nur 10 diits. Wenn Sie einen Antrag für mehrere Länder schreiben, sollten Sie eine umfassende Validierung durchführen.

Rendern: Ich schreibe ein benutzerdefiniertes Vorlagen-Tag, um es in der Vorlage schön zu rendern. Oder rendern Sie es sogar wie ein Bild - es ist sicherer, SMS-Spam zu verhindern.

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

Andere erwähnten django-phonenumber-field. Um das Anzeigeformat zu erhalten , wie Sie wollen , Sie brauchen , um Set - PHONENUMBER_DEFAULT_FORMATEinstellung "E164", "INTERNATIONAL", "NATIONAL", oder "RFC3966", wie Sie wollen es angezeigt. Siehe die GitHub-Quelle .

GoPackGo90
quelle