вторник, 9 октября 2012 г.

django:использование MultipleChoiceField в моделях

Сегодня натолкнулся на проблему... В django foms есть замечательное поле MultipleChoiceField. Позволяет, как не трудно догадаться, показывать пользователю контрол с возможностью множественного выбора.
Описывается , например, так (в классе формы):

EQUIPMENT_VARIANTS = ( 
 ('pm',u'Посудомоечная машина'),
 ('sm',u'Стиральная машина'),
 ('vr',u'Варка'),
 ('du',u'Духовка'),
 ('mi',u'Микроволновка'),
 ('ho',u'Холодильник'),
 ('vy',u'Вытяжка'), 


equipment = forms.MultipleChoiceField(choices=EQUIPMENT_VARIANTS, required=False)   

Все хорошо - форма рисуется, данные принимаются. Надо сохранить в БД.

Обнаруживается, что для Models поля-аналога нет.

Нормализовать БД, создавая новую словарную таблицу, не планирую и не хочу.

Хочу просто хранить список строк в одном поле.

Что ж, в соответствующей модели объявляем такое поле:

 equipment = models.CharField( max_length="1024", null=True, blank=True)

Привязываем форму к модели , используя forms.ModelForm.
Теперь данные сохраняются в БД. Но есть проблема. В БД они в таком виде: "[u'pm', u'sm']"

Когда все это затеивал знал, что для ChoiceField (вернее для CharField с аттрибутом choices) есть замечательная функция-хелпер get_FOO_display.

Замечательна она тем, что позволяет в шаблоне без лишних движений получить значение выбранной опции , а не мнемонику. Это нужно , например, при выводе превью формы или результата ее сабмита или вообще при выводе значения поля таблицы, которое описано с атрибутом choices.

Наивно полагал, что и для множественного выбора удастся в недрах django раскопать что-то подобное... Но увы. гуглеж выдал несколько решений с самопальными сниппетами и фильтрами. Не понравилось.

Проблему решил добавлением в модель специального метода для возможности получения удобочитаемого значения поля таблицы, в которое сохранен результат множественного выбора  

#не забыть import re 

def get_equipment_list(self): 
    p = re.compile('\'(\w+)\'') 
    result = [] 
    for e in p.findall(self.equipment): 
       for v in EQUIPMENT_VARIANTS: 
          if v[0] == e: 
             result.append(v[1]) 
    return result 

Функция получает список мнемоник значения поля equipment и формирует список значений опций из EQUIPMENT_VARIANTS - этот массив опций пришлось сделать видимым не только в классе формы , но и в классе модели.

Теперь в django-шаблоне можно спокойно получить для объекта результат множественного выбора из одного из его полей (в данном случае equipment).

Ну а дальше отрисовать этот список как угодно.

Надеюсь, кому-то сэкономит время.

Комментариев нет:

Отправить комментарий

Если Вы нашли ошибку у автора, у Вас есть вопрос или просто хотите поделиться чем-то полезным, то пишите - не стесняйтесь..