You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
232 lines
8.9 KiB
232 lines
8.9 KiB
# -*- coding: utf-8 -*-
|
|
from django import forms
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.utils.encoding import force_text
|
|
from django.db.models import ObjectDoesNotExist
|
|
from django.forms.models import ModelChoiceIterator
|
|
|
|
from theme.models import Theme
|
|
from haystack.query import SearchQuerySet
|
|
|
|
class AdminSearchForm(forms.Form):
|
|
search_name = forms.CharField(required=False, max_length=50)
|
|
|
|
|
|
class ThemeSearch(forms.Form):
|
|
event = forms.MultipleChoiceField(required=False,
|
|
widget=forms.CheckboxSelectMultiple(attrs={'class': 'topicChecks'}),
|
|
choices=[('exposition', _(u'выставки')),
|
|
('conference', _(u'конференции')),
|
|
('seminar', _(u'семинары')),
|
|
('webinar', _(u'вебинары'))])
|
|
theme = forms.ModelMultipleChoiceField(required=False, queryset=[],
|
|
widget=forms.CheckboxSelectMultiple)
|
|
|
|
|
|
|
|
from country.models import Area
|
|
class PlaceSearch(forms.Form):
|
|
r = forms.ModelMultipleChoiceField(queryset=Area.objects.all(), required=False,
|
|
widget=forms.CheckboxSelectMultiple())
|
|
c = forms.CharField(widget=forms.CheckboxSelectMultiple(), required=False)
|
|
t = forms.CharField(widget=forms.CheckboxSelectMultiple())
|
|
|
|
|
|
class AbstractSearch(forms.Form):
|
|
q = forms.CharField(label=_(u'Поиск'), required=False)
|
|
w = forms.CharField(label=_(u'Где'), required=False)
|
|
model = None
|
|
|
|
def search(self):
|
|
if not self.is_valid():
|
|
return []
|
|
|
|
q = self.cleaned_data.get('q')
|
|
w = self.cleaned_data.get('w')
|
|
|
|
if not q and not w:
|
|
return []
|
|
|
|
sqs = SearchQuerySet().models(self.model)
|
|
if q:
|
|
sqs = sqs.auto_query(q)
|
|
if w:
|
|
sqs = sqs.filter(where__contains=w)
|
|
|
|
return sqs
|
|
|
|
|
|
#sqs = SearchQuerySet().models(self.model).auto_query(self.cleaned_data.get('q'))
|
|
|
|
#return sqs
|
|
|
|
from place_exposition.models import PlaceExposition
|
|
from place_exposition.models import EXPOSITION_TYPE
|
|
|
|
class SearchPlaceExpositionForm(AbstractSearch):
|
|
model = PlaceExposition
|
|
type = forms.ChoiceField(choices=EXPOSITION_TYPE, required=False)
|
|
|
|
|
|
from django.conf import settings
|
|
from django.utils.translation import get_language
|
|
from django.forms.models import save_instance
|
|
|
|
class ExpoTranslatableModelForm(forms.ModelForm):
|
|
|
|
translatable_fields = []
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
inst = kwargs.get('instance')
|
|
veto_fields = ['id', 'master', 'language_code']
|
|
# all translated fields of object
|
|
self._all_tr_field_names = [field.name for field in self._meta.model.translations.related.editable_fields()
|
|
if field.name not in veto_fields]
|
|
|
|
if inst:
|
|
# populate fields
|
|
init_tr_data = self.fill_init_field(inst)
|
|
if kwargs['initial']:
|
|
kwargs['initial'].update(init_tr_data)
|
|
else:
|
|
kwargs.update({'initial': init_tr_data})
|
|
|
|
super(ExpoTranslatableModelForm, self).__init__(*args, **kwargs)
|
|
|
|
if not self.translatable_fields:
|
|
self.translatable_fields = self._all_tr_field_names
|
|
# generate Field objects by field name
|
|
fkwargs = {field.name: field for field in self._meta.model.translations.related.editable_fields()
|
|
if field.name not in veto_fields}
|
|
|
|
for code, name in settings.LANGUAGES:
|
|
for tr_field in self.translatable_fields:
|
|
field = fkwargs[tr_field].formfield()
|
|
if code != get_language():
|
|
field.required = False
|
|
self.fields[tr_field+"_"+code] = field
|
|
|
|
def clean(self):
|
|
data = self.cleaned_data
|
|
init_lang = get_language()[:2]
|
|
data.update(self.data_by_lang[init_lang])
|
|
return data
|
|
|
|
def save(self, commit=True):
|
|
# todo: fix commit False error
|
|
init_lang = get_language()[:2]
|
|
is_new = not self.instance.pk
|
|
inst = super(ExpoTranslatableModelForm, self).save()
|
|
|
|
if is_new:
|
|
for lang in self.data_by_lang:
|
|
if lang is not init_lang:
|
|
inst.translate(lang)
|
|
for key, value in self.data_by_lang[lang].items():
|
|
setattr(inst, key, value)
|
|
inst.save_translations(inst)
|
|
else:
|
|
translations = {obj.language_code: obj for obj in list(inst.translations.all())}
|
|
for lang in self.data_by_lang:
|
|
if lang is not init_lang:
|
|
translation = translations.get(lang)
|
|
# there are no available translation in db
|
|
if not translation:
|
|
translation = inst.translate(lang)
|
|
for key, value in self.data_by_lang[lang].iteritems():
|
|
setattr(translation, key, value)
|
|
translation.save()
|
|
|
|
self.instance = inst.lazy_translation_getter(init_lang)
|
|
return self.instance
|
|
|
|
@property
|
|
def data_by_lang(self):
|
|
res = {}
|
|
for lang in [code for code, _ in settings.LANGUAGES]:
|
|
res[lang] = {key[:-3]: self.cleaned_data[key] for key in self.cleaned_data
|
|
if key.endswith("_%s" % lang) and self.cleaned_data[key]}
|
|
result = {k: v for k, v in res.iteritems() if v}
|
|
return result
|
|
|
|
def fill_init_field(self, inst):
|
|
"""
|
|
|
|
:param inst:
|
|
:return: dictionary with populated fields format: {<field>_<language_code>: value}
|
|
"""
|
|
init_tr_data = {}
|
|
for code in inst.get_available_languages():
|
|
translation = inst.translations.get(language_code=code)
|
|
for field in self._all_tr_field_names:
|
|
init_tr_data[field+"_%s" % code] = getattr(translation, field)
|
|
return init_tr_data
|
|
|
|
|
|
class ExpoTranslatableModelForm_(ExpoTranslatableModelForm):
|
|
@property
|
|
def data_by_lang(self):
|
|
res = {}
|
|
for lang in [code for code, _ in settings.LANGUAGES]:
|
|
res[lang] = {key[:-3]: self.cleaned_data[key] for key in self.cleaned_data
|
|
if key.endswith("_%s" % lang) and self.cleaned_data[key]}
|
|
return res
|
|
|
|
|
|
class FieldsetMixin(object):
|
|
def fieldsets(self, fieldsets=None):
|
|
meta = getattr(self, 'Meta', None) or getattr(self, '_meta', None)
|
|
_fieldsets = fieldsets or meta.fieldsets
|
|
if _fieldsets:
|
|
for fs in _fieldsets:
|
|
yield {
|
|
'title': fs.get('title'),
|
|
'class': fs.get('class'),
|
|
'fields': (self[field] for field in fs.get('fields')) if fs.get('fields') else None,
|
|
'fieldsets': (fieldset for fieldset in self.fieldsets(fieldsets=fs.get('fieldsets'))) if fs.get('fieldsets') else None,
|
|
}
|
|
|
|
|
|
# class CustomModelChoiceIterator(ModelChoiceIterator):
|
|
# def __init__(self, field):
|
|
# self.field = field
|
|
# self.queryset = getattr(field, 'c_queryset', field.queryset.none())
|
|
|
|
|
|
class OrderedSelectMultiple(forms.SelectMultiple):
|
|
def render_options(self, choices, selected_choices):
|
|
selected_choices = set(selected_choices)
|
|
self.choices.queryset = self.choices.queryset.filter(pk__in=selected_choices)
|
|
choices = dict(self.choices)
|
|
selected_choices_str = set(force_text(v) for v in selected_choices)
|
|
output = []
|
|
for choice in selected_choices:
|
|
label = choices.get(choice)
|
|
if label:
|
|
output.append(self.render_option(selected_choices_str, choice, label))
|
|
# unselected_choices = set(choices.iterkeys()).difference(selected_choices)
|
|
# if unselected_choices:
|
|
# for option_value, option_label in filter(lambda x: x[0] in unselected_choices, choices.iteritems()):
|
|
# if isinstance(option_label, (list, tuple)):
|
|
# output.append(format_html('<optgroup label="{0}">', force_text(option_value)))
|
|
# for option in option_label:
|
|
# output.append(self.render_option(selected_choices_str, *option))
|
|
# output.append('</optgroup>')
|
|
# else:
|
|
# output.append(self.render_option(selected_choices_str, option_value, option_label))
|
|
return '\n'.join(output)
|
|
|
|
|
|
class ML_ModelMultipleChoiceField(forms.ModelMultipleChoiceField):
|
|
widget = OrderedSelectMultiple
|
|
# def _get_choices(self):
|
|
# if hasattr(self, '_choices'):
|
|
# return self._choices
|
|
# return CustomModelChoiceIterator(self)
|
|
# choices = property(_get_choices, forms.ChoiceField._set_choices)
|
|
|
|
|
|
class EmptySelect(forms.Select):
|
|
def render_option(self, selected_choices, option_value, option_label):
|
|
return ''
|
|
|
|
|