# -*- 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: {_: 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): 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('', force_text(option_value))) # for option in option_label: # output.append(self.render_option(selected_choices_str, *option)) # output.append('') # 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)