Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Несколько пригодных полей Django

Anna | 15.06.2014 | нет комментариев
Я тружусь штатным программистом в Санкт-Петербургском Государственном Экономическом Институте и моей задачей с недавних пор является сопровождение деятельности отдела фото-видео производства (начинающее университетское телевидение). Как только руководитель управления попросил всех зарегистрироваться в 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(длинна номера).

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>
 7{{ 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),]  
#Первое число - порядковый номер, второе - значение. В списке будут только значения.             

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

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB