Джанго номер телефона

  1. Сохранение телефонных номеров с помощью PhoneNumberField стороннего приложения Django
  2. Сохранение телефонных номеров с помощью валидатора и модели Django

Лучшие способы хранения телефонных номеров в Django

При создании базы данных мы часто сталкиваемся с проблемами, когда не можем определить тип поля для конкретных данных. Чаще всего мы не понимаем, как организовать некоторые типы полей. Например: если нам нужно сохранить уникальный номер, мы должны выбрать между символьным полем или целочисленным полем. У каждого типа поля есть свои преимущества и недостатки.

Одним из таких данных является номер телефона; сохраняя номер телефона, мы должны убедиться, что в поле можно хранить номера телефонов из любой точки мира. Мы должны убедиться, что мы храним код страны вместе с самим номером телефона.

В этой статье рассказывается о некоторых из лучших способов сохранить номер телефона в Django.

Сохранение телефонных номеров с помощью PhoneNumberField стороннего приложения Django

Для хранения телефонных номеров мы можем использовать стороннее приложение или библиотеку Django, в которых реализовано это поле: PhoneNumberField.

Вы можете найти репозиторий GitHub этой библиотеки или приложения здесь.

Согласно официальному README, эта библиотека Django может проверять и преобразовывать телефонные номера. Эта библиотека взаимодействует с другой библиотекой Python, python-phonenumbers, которая является портом библиотеки Google libphonenumber, которая обеспечивает обработку телефонных номеров Android.

Установите библиотеку Django

Эту библиотеку Django можно загрузить с помощью следующей команды pip:

pip install django-phonenumber-field[phonenumbers]

Поскольку это обширная библиотека с точки зрения размера, вы можете загрузить более легкую версию. Чтобы загрузить более легкую версию этой библиотеки, используйте команду ниже:

pip install django-phonenumber-field[phonenumberslite]

Настроить библиотеку Django

Чтобы использовать это приложение или библиотеку, мы должны добавить их в файл settings.py нашего проекта. Имя приложения необходимо ввести в INSTALLED_APPS следующим образом:

INSTALLED_APPS = [
    # Other apps
    "phonenumber_field",
]

Используйте библиотеку Django

В этой библиотеке есть поле модели PhoneNumberField, которое можно использовать для хранения телефонных номеров. Наша модель будет выглядеть примерно так:

from phonenumber_field.modelfields import PhoneNumberField

class Person(models.Model):
    firstName = models.CharField(max_length = 100)
    middleName = models.CharField(max_length = 100)
    lastName = models.CharField(max_length = 100)
    phoneNumber = PhoneNumberField(unique = True, null = False, blank = False) # Here
    secondPhoneNumber = PhoneNumberField(null = True, blank = True) # Here

Поле PhoneNumberField внутренне основано на пространстве CharField и хранит номера в виде строки в соответствии с международными стандартами телефонных номеров.

Чтобы узнать больше об этой библиотеке, обратитесь к официальной документации.

Теперь, чтобы получить доступ к значениям этого поля, мы напишем инструкцию Python, которая выглядит примерно так:

person = models.Person.objects.get(id = 25)
phoneNumber = person.phoneNumber.as_e164

Здесь номер телефона возвращается в виде строки в стандарте E.164 из-за as_e164. E.164 — это международный стандарт хранения телефонных номеров. Вы можете прочитать больше об этом здесь].

Сохранение телефонных номеров с помощью валидатора и модели Django

Если вы не хотите использовать стороннее приложение Django и хранить телефонные номера с использованием моделей Django, вы можете использовать Validator и CharField. Следующий код показывает то же самое:

from django.core.validators import RegexValidator

class Person(models.Model):
    phoneNumberRegex = RegexValidator(regex = r"^+?1?d{8,15}$")
    phoneNumber = models.CharField(validators = [phoneNumberRegex], max_length = 16, unique = True)

Валидатор phoneNumberRegex проверяет значение, введенное для CharField. Опять же, номера телефонов хранятся в формате E.164.

CharField имеет максимальную длину 16 символов, потому что стандарт E.164 допускает максимум 15 цифр для номера. Пятнадцать символов включают код страны и номер телефона. Дополнительный символ зарезервирован для знака +, который является префиксом кода страны.

First, install «django-phonenumber-field» package with the command below:

pip install django-phonenumber-field[phonenumbers]

Then, set «phonenumber_field» to INSTALLED_APPS in «settings.py»:

# "settings.py"

INSTALLED_APPS = [
    ...
    "phonenumber_field",
    ...
]

Then, set a field with «PhoneNumberField()» in «models.py»:

# "models.py"

from django.db import models
from phonenumber_field.modelfields import PhoneNumberField

class Contact(models.Model):
    phone = PhoneNumberField()

Then, register «Contact» in «admin.py»:

# "admin.py"

from django.contrib import admin
from .models import Contact

@admin.register(Contact)
class ContactAdmin(admin.ModelAdmin):
    pass

Then, run the command below:

python manage.py makemigrations && python manage.py migrate

Now, the field for a phone number is created as shown below:

enter image description here

In addition, assign the widget «PhoneNumberPrefixWidget()» to the field in a custom form and assign the custom form to the admin as shown below:

# "admin.py"

from django.contrib import admin
from .models import Contact
from django import forms
from phonenumber_field.widgets import PhoneNumberPrefixWidget

class ContactForm(forms.ModelForm):
    class Meta:
        widgets = {
            'phone': PhoneNumberPrefixWidget(),
        }

@admin.register(Contact)
class ContactAdmin(admin.ModelAdmin):
    form = ContactForm

Now, with country codes, the field for a phone number is created

enter image description here

And, you can set an initial country code like initial=’US’ to «PhoneNumberPrefixWidget()» as shown below. *Initial country code must be uppercase:

# "admin.py"

from django.contrib import admin
from .models import Contact
from django import forms
from phonenumber_field.widgets import PhoneNumberPrefixWidget

class ContactForm(forms.ModelForm):
    class Meta:
        widgets = {                          # Here
            'phone': PhoneNumberPrefixWidget(initial='US'),
        }

@admin.register(Contact)
class ContactAdmin(admin.ModelAdmin):
    form = ContactForm

Now, with the initial country code «US» selected, the field for a phone number is created:

enter image description here

You can also set an initial country code with «PHONENUMBER_DEFAULT_REGION» in «settings.py» as shown below but I recommand to set an initial country code with initial=’US’ to «PhoneNumberPrefixWidget()» as I’ve done above because using «PHONENUMBER_DEFAULT_REGION» sometimes doesn’t display saved phone numbers in Django Admin:

# "settings.py"

PHONENUMBER_DEFAULT_REGION = "US"

Я работаю штатным программистом в Санкт-Петербургском Государственном Экономическом Университете и моей задачей с недавних пор является сопровождение деятельности отдела фото-видео производства (начинающее университетское телевидение). Как только начальник управления попросил всех зарегистрироваться в Bitrix24 с целью автоматизировать отчёты, я подумал об автоматизации входящих задач (на самом деле всё немного глубже и целью была дисциплина, но к посту не относится).

Собственно, первом делом я взялся за форму заявки на фото-видео съёмку, которую, недолго думая, набросал в Django. К этому моменту мои познания фрэймворка ограничивались несколькими представлениями для вывода списков на внутреннем сервере отдела. Основной сложность в форме стали

внезапно

поля — хотелось одновременно и красоту навести и от ошибок ввода пользователя уберечь(ся). Особенно интересовали меня два поля — поле ввода телефона и выбора времени. О них и речь.

Начну с поля для ввода телефона. Сначала я обратился к Хабру и нашёл некий пост, однако увиденное показалось мне слишком громоздким для моей цели (ведь мне надо было просто передать телефон оператору). Я понял, что использование CharField не приведёт ни к одной из моих целей и, пошуршав документацией Django, я нашёл там MultiValueField и MultiWidget в дополнение (сразу хочу сказать, что использование только MultiValueField порождает обычную строку для ввода текста, что никакого смысла не имеет). Через несколько минут был написан код под катом.

1) Для начала импортируем необходимое.

from django.forms import MultiValueField, CharField, ChoiceField, MultiWidget, TextInput, Select

2) Затем определяем PhoneWidget, базовым классом для которого будет MultiWidget.

class PhoneWidget(MultiWidget):
    def __init__(self, code_length=3, num_length=7, attrs=None):
        widgets = [TextInput(attrs={'size': code_length, 'maxlength': code_length}),
                   TextInput(attrs={'size': num_length, 'maxlength': num_length})]
        super(PhoneWidget, self).__init__(widgets, attrs)

    def decompress(self, value):
        if value:
            return [value.code, value.number]
        else:
            return ['', '']

Немного пояснений:
Длина кода города в Санкт-Петербурге и мобильных всея Руси — 3 символа, а самого телефона — 7. Но и тот и другой параметр могут меняться, поэтому они и были указаны в конструкторе с дефолтными значениями, подходящими для меня.
Далее идёт определение 2х самих виджетов (думаю, для понимания можно назвать их представлениями полей) с ограничениями длинны поля ввода (для красоты) и количества символов (для защиты от ошибок) параметрами code_length(длина кода) и num_length(длина номера).

Красоты

феншуя

ради я добавил ещё метод format_output()

def format_output(self, rendered_widgets):
        return '+7' + '(' + rendered_widgets[0] + ') - ' + rendered_widgets[1]

дабы получить на выходе красивое форматирование в html.

3) Определяем само поле базовым классом для которого будет MultiValueField.

class PhoneField(MultiValueField):
    def __init__(self, code_length, num_length, *args, **kwargs):
        list_fields = [CharField(),
                       CharField()]
        super(PhoneField, self).__init__(list_fields, widget=PhoneWidget(code_length, num_length), *args, **kwargs)

    def compress(self, values):
        return '+7' + values[0] + values[1]  #Собственно, стандартизация строки номера эстетики ради

Немного пояснений:
В конструкторе содержатся те же параметры для передачи конструктору виджета. Иначе, как я уже писал, мы получим обычную строку для ввода текста.

4) В итоге в форме мы указываем поле

p_num = PhoneField()  
#При желаниинеобходимости можно вызвать с параметрами: PhoneField(code_length=some_value, num_length=some_value)

и, добавив в шаблон

{{ form.p_num.errors }}
<label for="phone_num">Номер телефона:</label>
</br>
{{ form.p_num }}

мы получаем два красивых поля длинной 3 и 7 (или сколько указано) символов и международным кодом впереди для его стандартизации и подсказки полльзователю.

По аналогии были сделаны виджет и поле для ввода времени:

class TimeWidget(MultiWidget):
    def __init__(self, h_choices, m_choices, attrs=None):
        widgets = [Select(choices=h_choices),
                   Select(choices=m_choices)]
        super(TimeWidget, self).__init__(widgets, attrs)

    def decompress(self, value):
        if value:
            return [value.hours, value.minutes]
        else:
            return ['', '']


class TimeField(MultiValueField):
    def __init__(self, h_choices, m_choices, *args, **kwargs):
        list_fields = [ChoiceField(),
                       ChoiceField()]
        super(TimeField, self).__init__(list_fields, widget=TimeWidget(h_choices, m_choices),*args, **kwargs)

    def compress(self, values):
        return return values[0] + ':' + values[1]  #Стандартизация для приведения впоследствии к объекту datetime

Для защиты пользователя от указания времени вне рабочего дня, а также вне разумного лимита (24 и 60) я сделал 2 списка с выбором параметром.

Вызов:

time = TimeField(h_choices=HOURS_CHOICES, m_choices=MINUTES_CHOICES)

И сами параметры (в соответствии с документацией Django должны быть списком кортежей и определяться вне класса формы):

HOURS_CHOICES = [(str(x), x) for x in range(9, 21)]  
#Даю на выбор лишь разумное рабочее время, чтобы не ворчали операторы
MINUTES_CHOICES = [(1, 0), (2, 10), (3, 20), (4, 30), (5, 40), (6, 50),]  
#Первое число - порядковый номер, второе - значение. В списке будут только значения.             

Осталось только понять, как между полями вставлять некие символьные разделители (например, ‘:’ между часами и минутами), но функциональной нагрузки это не несёт. Впрочем, я постараюсь решить и эту задачу и дополню пост найденным решением, а также другими примерами полей.

UPD: описан метод format_output() для получения

всяких скобочек рюшечек

опрятного форматирования.

I want to add PhoneNumberField so I can use take phone number of user at time registration. I already have UserCreationForm model which is used by CreateUserForm to create a new User. However by default it does not phone number field. I tried adding it by adding phone variable in forms.py but it does not work giving the error below.

forms.py

class CreateUserForm(UserCreationForm):
    phone=PhoneNumberField()
    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2', 'phone']

models.py

class CustomerReg(models.Model):
    user=models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
    name=models.CharField(max_length=200, null=True)
    email=models.EmailField(max_length=254)
    phone=PhoneNumberField(default=None)
def create_profile(sender, **kwargs):
    if kwargs['created']:
        user_profile=CustomerReg.objects.create(user=kwargs['instance'])

post_save.connect(create_profile, sender=User)

This is Error I get when I run python manage.py makemigrations

Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    main()
  File "manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "D:djangoL2GvenvPlibsite-packagesdjangocoremanagement__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "D:djangoL2GvenvPlibsite-packagesdjangocoremanagement__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "D:djangoL2GvenvPlibsite-packagesdjangocoremanagementbase.py", line 330, in run_from_argv
    self.execute(*args, **cmd_options)
  File "D:djangoL2GvenvPlibsite-packagesdjangocoremanagementbase.py", line 368, in execute
    self.check()
  File "D:djangoL2GvenvPlibsite-packagesdjangocoremanagementbase.py", line 396, in check
    databases=databases,
  File "D:djangoL2GvenvPlibsite-packagesdjangocorechecksregistry.py", line 70, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "D:djangoL2GvenvPlibsite-packagesdjangocorechecksurls.py", line 13, in check_url_config
    return check_resolver(resolver)
  File "D:djangoL2GvenvPlibsite-packagesdjangocorechecksurls.py", line 23, in check_resolver
    return check_method()
  File "D:djangoL2GvenvPlibsite-packagesdjangourlsresolvers.py", line 408, in check
    for pattern in self.url_patterns:
  File "D:djangoL2GvenvPlibsite-packagesdjangoutilsfunctional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "D:djangoL2GvenvPlibsite-packagesdjangourlsresolvers.py", line 589, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "D:djangoL2GvenvPlibsite-packagesdjangoutilsfunctional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "D:djangoL2GvenvPlibsite-packagesdjangourlsresolvers.py", line 582, in urlconf_module
    return import_module(self.urlconf_name)
  File "C:PythonPython36libimportlib__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "D:DjangoL2Gwizl2gprojectl2gProjecturls.py", line 23, in <module>
    path('',include('customer.urls')),
  File "D:djangoL2GvenvPlibsite-packagesdjangourlsconf.py", line 34, in include
    urlconf_module = import_module(urlconf_module)
  File "C:PythonPython36libimportlib__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "D:DjangoL2Gwizl2gprojectcustomerurls.py", line 2, in <module>
    from . import views
  File "D:DjangoL2Gwizl2gprojectcustomerviews.py", line 6, in <module>
    from .forms import CreateUserForm
  File "D:DjangoL2Gwizl2gprojectcustomerforms.py", line 35, in <module>
    class CreateUserForm(UserCreationForm):
  File "D:djangoL2GvenvPlibsite-packagesdjangoformsmodels.py", line 268, in __new__
    raise FieldError(message)
django.core.exceptions.FieldError: Unknown field(s) (phone) specified for User

How do I add phone number field to my form then?

I want to add PhoneNumberField so I can use take phone number of user at time registration. I already have UserCreationForm model which is used by CreateUserForm to create a new User. However by default it does not phone number field. I tried adding it by adding phone variable in forms.py but it does not work giving the error below.

forms.py

class CreateUserForm(UserCreationForm):
    phone=PhoneNumberField()
    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2', 'phone']

models.py

class CustomerReg(models.Model):
    user=models.OneToOneField(User, null=True, blank=True, on_delete=models.CASCADE)
    name=models.CharField(max_length=200, null=True)
    email=models.EmailField(max_length=254)
    phone=PhoneNumberField(default=None)
def create_profile(sender, **kwargs):
    if kwargs['created']:
        user_profile=CustomerReg.objects.create(user=kwargs['instance'])

post_save.connect(create_profile, sender=User)

This is Error I get when I run python manage.py makemigrations

Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    main()
  File "manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "D:djangoL2GvenvPlibsite-packagesdjangocoremanagement__init__.py", line 401, in execute_from_command_line
    utility.execute()
  File "D:djangoL2GvenvPlibsite-packagesdjangocoremanagement__init__.py", line 395, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "D:djangoL2GvenvPlibsite-packagesdjangocoremanagementbase.py", line 330, in run_from_argv
    self.execute(*args, **cmd_options)
  File "D:djangoL2GvenvPlibsite-packagesdjangocoremanagementbase.py", line 368, in execute
    self.check()
  File "D:djangoL2GvenvPlibsite-packagesdjangocoremanagementbase.py", line 396, in check
    databases=databases,
  File "D:djangoL2GvenvPlibsite-packagesdjangocorechecksregistry.py", line 70, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "D:djangoL2GvenvPlibsite-packagesdjangocorechecksurls.py", line 13, in check_url_config
    return check_resolver(resolver)
  File "D:djangoL2GvenvPlibsite-packagesdjangocorechecksurls.py", line 23, in check_resolver
    return check_method()
  File "D:djangoL2GvenvPlibsite-packagesdjangourlsresolvers.py", line 408, in check
    for pattern in self.url_patterns:
  File "D:djangoL2GvenvPlibsite-packagesdjangoutilsfunctional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "D:djangoL2GvenvPlibsite-packagesdjangourlsresolvers.py", line 589, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "D:djangoL2GvenvPlibsite-packagesdjangoutilsfunctional.py", line 48, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "D:djangoL2GvenvPlibsite-packagesdjangourlsresolvers.py", line 582, in urlconf_module
    return import_module(self.urlconf_name)
  File "C:PythonPython36libimportlib__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "D:DjangoL2Gwizl2gprojectl2gProjecturls.py", line 23, in <module>
    path('',include('customer.urls')),
  File "D:djangoL2GvenvPlibsite-packagesdjangourlsconf.py", line 34, in include
    urlconf_module = import_module(urlconf_module)
  File "C:PythonPython36libimportlib__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 994, in _gcd_import
  File "<frozen importlib._bootstrap>", line 971, in _find_and_load
  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 678, in exec_module
  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed
  File "D:DjangoL2Gwizl2gprojectcustomerurls.py", line 2, in <module>
    from . import views
  File "D:DjangoL2Gwizl2gprojectcustomerviews.py", line 6, in <module>
    from .forms import CreateUserForm
  File "D:DjangoL2Gwizl2gprojectcustomerforms.py", line 35, in <module>
    class CreateUserForm(UserCreationForm):
  File "D:djangoL2GvenvPlibsite-packagesdjangoformsmodels.py", line 268, in __new__
    raise FieldError(message)
django.core.exceptions.FieldError: Unknown field(s) (phone) specified for User

How do I add phone number field to my form then?

Profile views
GitHub top language
GitHub language count
GitHub code size in bytes
GitHub repo size
GitHub
GitHub last commit

GitHub User's stars

Сайт телефонный корпоративный справочник



Сайт телефонный корпоративный справочник написан на фреймворке python Django, используется по умолчанию СУБД SQLite3. В данном проекте используются:

  • одно приложение ‘phonebook’, применяется двухуровневый шаблон страниц (с подгрузкой навбара и сайдбара);
  • подключена статика bootstrap в локальном режиме (позволяет запустить сервер офлайн) все элементы сохранят свой вид;
  • реализованы пользовательские теги;
  • реализованы формы заполнения данных;
  • реализована регистрация, вход, аутентификция и разграничение прав пользователей;
  • реализована пагинация данных;
  • применяются мексины;
  • подключено приложение для отладки сайта DebagToolbar.

Содержание проекта:

  • папка data — место хранения исходных капч (5 цифр)

  • README.md — описание проекта

  • update_pakets.py — обновление пакетов проекта в автоматическом режиме

  • django_command — описание команд python при подготовке проекта и его запуска

  • for_mysql.py — проверка подключения к базе данных MySQL

  • папка phonebooke_site — размещение проекта

  • db.sqlite3 — база данных sqlite3

  • manage.py — основной исполняемый файл сайта

  • my.cnf — конфигурация MySQL

  • mySQL_command — команды MySQL

  • django_cache — папка для хранения кеша

  • media — папка хранения медиафайлов (фотографий)

  • phonebook — папка приложения телефонный справочник

  • phonebooke_site — папка размещения основы сайта

  • static — папка для размещения статических файлов

  • templates — папка хранения htmal страниц


Библиотеки применяемые в проекте:

  • settings — подгружаем настройки в режиме отладки
  • static, path, include, reverse_lazy — для работы с статическими, ленивыми и url адресами
  • forms — модуль работы с формами
  • re — модуль регулярных выражений, для работы с данными в форме (для применения собственных проверок
  • ValidationError — модуль обработок собственных ошибок
  • UserCreationForm, AuthenticationForm — модуль регистрации пользователя и логирования
  • User — модуль работы с пользователями
  • send_mail — модуль отправки сообщений
  • models — импортируем модуль работы с базами данных
  • LoginRequiredMixin — импортируем штатный миксин проверки аутентификации
  • Paginator — пагинация страниц
  • UserCreationForm — создание формы регистрации пользователя
  • messages — модуль сообщений
  • login, logout — модуль логирования и выхода
  • send_mail — модуль отправки сообщений
  • Count, F — модуль подсчета значений и фильтрации

Клонируем репозиторий (Clone the repository)

$ cmd
$ git clone https://github.com/BEPb/first.git
$ cd django-phonebook

Устанавливаем необходимые пакеты (Install dependencies)

$ pip install -r requirements.txt / pipenv install

Запускаем локальный сервер (Run the application locally)

$ python manage.py runserver

Открывает Ваш браузер по адресу http://localhost:8000/

Вопрос:

Я храню номер телефона в model как это:

phone_number = models.CharField(max_length=12)

Пользователь будет вводить номер телефона, и я буду использовать номер телефона для SMS Authentication Это приложение будет использоваться во всем мире. Поэтому мне также понадобится код страны. Является ли CharField хорошим способом хранения номера телефона? И как мне проверить номер телефона?

Заранее спасибо.

Лучший ответ:

Вы можете взглянуть на международный стандартизированный формат E.164, рекомендованный, например, Twilio (у которого есть сервис и API для отправки SMS или телефонных звонков через запросы REST).

Это, вероятно, самый универсальный способ хранения телефонных номеров, особенно если вы работаете с международными номерами.

1. Телефон по PhoneNumberField

Вы можете использовать библиотеку phonenumber_field. Это порт библиотеки Google libphonenumber, которая обеспечивает обработку телефонных номеров Android https://github.com/stefanfoulis/django-phonenumber-field

В модели:

from phonenumber_field.modelfields import PhoneNumberField

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

Сообщить:

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

Получить телефон в виде строки из поля объекта:

    client.phone.as_e164 

Нормализировать телефонную строку (для тестов и другого персонала):

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

2. Телефон по регулярному выражению

Одно замечание для вашей модели: максимальная длина символа E.164 равна 15.

Для проверки вы можете использовать некоторую комбинацию форматирования, а затем сразу же пытаться связаться с номером для подтверждения.

Я думаю, что я использовал что-то вроде следующего в моем проекте 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."))

РЕДАКТИРОВАТЬ

Похоже, что этот пост был полезен для некоторых людей, и, кажется, стоит интегрировать приведенный ниже комментарий в более полноценный ответ. В соответствии с jpotter6, вы можете сделать что-то вроде следующего на ваших моделях:

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

Ответ №1

Ответ №2

Ответ №3

Проверка проста, назовите их небольшим кодом для ввода. CharField – отличный способ его сохранить. Я не стал бы слишком беспокоиться о канонизации номеров телефонов.

Ответ №4

Все зависит от того, что вы понимаете как номер телефона. Номера телефонов специфичны для страны. Пакеты localflavors для нескольких стран содержат свое собственное поле “номер телефона”. Так что, если вы в порядке, специфические для страны, вы должны взглянуть на пакет localflavor (class us.models.PhoneNumberField для случая в США и т.д.).

В противном случае вы можете проверить локальных злоумышленников, чтобы получить максимальную длину для всех стран. Localflavor также имеет поля форм, которые вы могли бы использовать в сочетании с кодом страны для подтверждения номера телефона.

Ответ №5

Я опишу, что я использую:

Валидация: строка содержит более 5 цифр.

Очистка: удаление всех символов без цифр, запись только в числах. Мне повезло, потому что в моей стране (Россия) у всех есть номера телефонов с 10 цифрами. Поэтому я храню в db всего 10 децитов. Если вы пишете многостраничное приложение, вы должны сделать всестороннюю проверку.

Рендеринг: я пишу специальный тег шаблона, чтобы сделать его в шаблоне красиво. Или даже сделать это как изображение – безопаснее предотвращать спам-спам.

Ответ №6

#python #django #django-models #django-views #django-forms

Вопрос:

Итак, текущая проблема, с которой я сталкиваюсь, заключается в том, что в настоящее время у меня есть форма для создания пользователя, которую мы сейчас добавляем в опцию номера телефона для этого, в настоящее время создается пользователь и профиль пользователя, но в профиле пользователя не сохранен номер телефона. Единственный способ, которым я смог его ввести, — это вручную через страницу администратора django

Я попробовал несколько вариантов, но ни один из них пока не работает. Я ценю любую помощь, которую могу получить

#это в моем forms.py

 class UserRegisterForm(UserCreationForm):
    email = forms.EmailField()
    class Meta:
        model = User
        fields = ['username', 'email', 'password1', 'password2']
        #fields = UserCreationForm.Meta.fields  ('username', 'email', 'password1', 'password2')
        
    def clean(self):
        email = self.cleaned_data.get('email')
        username = self.cleaned_data.get('username')
        if email and User.objects.filter(email=email).exclude(username=username).exists():
            raise forms.ValidationError('Email addresses must be unique.')
        return super().clean()


class UserProfileForm(forms.ModelForm):
    class Meta:
        model = UserProfile
        fields = ['phone_number']
 

это мое views.py

 def register(request):
    if request.method == 'POST':
        form = UserRegisterForm(request.POST)
        profile_form = UserProfileForm(request.POST) #added
        if form.is_valid() and profile_form.is_valid(): #addded profile form
            form.save()
            profile_form.save() #added
            messages.success(request, 'Account created!')
            return redirect('login')
    else:
        form = UserRegisterForm()
        profile_form = UserProfileForm() #added

    return render(request, 'user/register.html', {'form': form, 'profile_form': profile_form})
 

это мое register.html

     <form method="post">
      {% csrf_token %}
      <fieldset class="form-group">
        <legend class="border-bottom mb-4">Register</legend>
        {{ form|crispy }}
        <!-- {{ profile_form.as_p }} -->
      </fieldset>
      <div class="form-group">
        <button type="submit" class="btn btn-outline-info">Sign Up</button>
      </div>
    </form>
 

this is my models.py

 class UserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
    qr_token = models.CharField(max_length=24, unique=True)
    image = models.ImageField(default='default.png', upload_to='profile_pics')
    date_created = models.DateTimeField(auto_now_add=True)
    is_before_user = models.BooleanField(default=True)
    phone_number = PhoneField(null=True, help_text='Contact phone number')
#there is more of it but the rest isnt relevent
 

Понравилась статья? Поделить с друзьями:
  • Джамиля кафланова номер телефона
  • Дешевое такси электросталь номера телефонов
  • Дешевое такси череповец номера телефонов
  • Дешевое такси челябинск номер телефона цена проезда
  • Дешевое такси ухта номера телефонов