Наши пользователи следят за спецпредложениями авиакомпаний и дешевыми перелетами, каждому интересно своё направление, пунктов вылета и прилета — тысячи, пользователи хотят одновременно следить за несколькоми городами, странами или регионами. Появилась задача — как предоставить удобный механизм подписки? Без долгого тыканья в мульти селект, без кнопок «Добавить пункт вылета». Ответ выглядит так —
Решением стал контрол из Фейсбука и Контакта — пользователи знакомы с ним, а значит не нужно объяснять как он работает. Осталось скрестить его с django.
Этот контрол подойдет для многих случаев когда нужна выборка из большого списка — сотнями или тысячами элементов.
Живой пример — на форме выбора городов для отcлеживания акций авиакомпаний.
Со стророны юзера используем готовый jquery plug-in, доступный на www.emposha.com/javascript/fcbkcomplete.html, скачиваем его и кладем css и js в папку media ( в моём случае — media/css и media/js )
Добавим код формы в foms.py-
Последняя строчка — основная, если у формы есть инициализационные значения — заполним choices.
В html файл с формой добавим инициалиазацию контролов:
Для того чтобы работал автопокомплит — добавим вьюху, которая будет генерировать необходимый json В нашем случае он расположен по адресу — /subscribe_autocomplete. Итак добавляем — в urls.py:
во views.py:
теперь у нас работает форма на странице и успешно генериться заполненная форма из пост заспроса (form = SubscriptionFilterForm(request.POST) )
Для генерации формы из модели — использую отдельную функцию ( в моем случае ModelsForm не подошел )
Решением стал контрол из Фейсбука и Контакта — пользователи знакомы с ним, а значит не нужно объяснять как он работает. Осталось скрестить его с django.
Этот контрол подойдет для многих случаев когда нужна выборка из большого списка — сотнями или тысячами элементов.
Живой пример — на форме выбора городов для отcлеживания акций авиакомпаний.
Со стророны юзера используем готовый jquery plug-in, доступный на www.emposha.com/javascript/fcbkcomplete.html, скачиваем его и кладем css и js в папку media ( в моём случае — media/css и media/js )
Добавим код формы в foms.py-
class MultiOriginSelect(forms.SelectMultiple):
class Media:
css = {
'all': ('/media/css/fcbkinput.css',)
}
js = ('/media/js/jquery.fcbkcomplete.js')
class SubscriptionFilterForm(forms.Form):
CHOICES =[]
........
orgs = forms.MultipleChoiceField(widget=MultiOriginSelect, choices=CHOICES, required=False, initial=[])
dsts = forms.MultipleChoiceField(widget=MultiOriginSelect, choices=CHOICES, required=False, initial=[])
........
def __init__(self, *args, **kwargs):
super(SubscriptionFilterForm, self).__init__(*args, **kwargs)
fcbkcomplete_fields = [u'orgs', u'dsts']
for field in fcbkcomplete_fields:
# check whether we have init parameters
if args:
loc_list = args[0].getlist(field)
.....
# generate dynamic choices for fcbk fields from args, like [id, name]
self.fields[field].choices = ([(int(o), name(o)) for o in loc_list] )
Последняя строчка — основная, если у формы есть инициализационные значения — заполним choices.
В html файл с формой добавим инициалиазацию контролов:
<head>
<script>
$(document).ready(function(){
$("#id_orgs, #id_dsts").fcbkcomplete({
json_url:'/subscribe_autocomplete',
first_selected:false,
filter_hide : true,
filter_case:false,
complete_text:"Enter country, city or airport.",
maxitems: 100
});
});
</script>
</head>
<body>
....
<form>
......
{{form.orgs}}
{{form.dsts}}
<input type = "submit">
</form>
......
</body>
Для того чтобы работал автопокомплит — добавим вьюху, которая будет генерировать необходимый json В нашем случае он расположен по адресу — /subscribe_autocomplete. Итак добавляем — в urls.py:
.....
url(r'^subscribe_autocomplete', subscribe_autocomplete, name='subscribe_autocomplete'),
.....
во views.py:
def subscribe_autocomplete(request):
q = request.GET.get('tag','')
# skip too short requests
if len(q)<3: return HttpResponse('')
# filter any instances according to tag
qr = Objects.objects.filter(Q(....))
#generate json
#message format - [{"caption":"London", "value":4}]
s =[...];
return HttpResponse(s)
теперь у нас работает форма на странице и успешно генериться заполненная форма из пост заспроса (form = SubscriptionFilterForm(request.POST) )
Для генерации формы из модели — использую отдельную функцию ( в моем случае ModelsForm не подошел )
def subs_form_from_model(s):
src_d = {}
src_d['subscriptionemail'] = s.email
,,,,
qd = django.http.QueryDict('')
qd = qd.copy() # to make muttable
qd.update(src_d)
# fill form fields
qd.setlist('orgs', [unicode(o.id) for o in s.orgs.all()])
qd.setlist('dsts', [unicode(d.id) for d in s.dsts.all()])
# create form
form = SubscriptionFilterForm(qd)
..........
return form</code>
Большинство пользователей видит поле уже заполненным ( по гео айпи ) и понимает что к чему.
Такую же форму можно ( и нужно ) использовать в админке, для больших мени-ту-мени полей.
PS И чтобы два раза не вставать — если вам понравились буруки (или вы уже пользуетесь нашем поиском и рассылкой) — с радостью пообщаемся с умелым верстальщиком и акробатом JSа.