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.
 
 
 
 
 
 

136 lines
5.1 KiB

# -*- coding: utf-8 -*-
from itertools import chain
from django import forms
from django.utils.translation import ugettext as _
from django.utils.encoding import smart_text, force_text
from django.utils.html import format_html
from django.utils.safestring import mark_safe
from django.db.models import Count, Sum
from haystack.query import SearchQuerySet, RelatedSearchQuerySet
from functions.model_utils import EnumChoices
from exposition.models import Exposition
from conference.models import Conference
from theme.models import Theme, Tag
class CountModelMultipleChoiceField(forms.ModelMultipleChoiceField):
def label_from_instance(self, obj):
return u'{0} ({count})'.format(smart_text(obj.name), count=obj.e_count + obj.c_count)
### Делаем выборку по темам, сразу заполняя перевод и кол-во событиый
## 1-й рабочий способ (без заполнения перевода)
# """
# SELECT
# `theme_theme`.`id`,
# (
# SELECT COUNT(`exposition_exposition_theme`.`exposition_id`)
# FROM `exposition_exposition_theme`
# WHERE (`theme_theme`.`id` = `exposition_exposition_theme`.`theme_id`)
# ) AS `e_count`,
# (
# SELECT COUNT(`conference_conference_theme`.`conference_id`)
# FROM `conference_conference_theme`
# WHERE (`theme_theme`.`id` = `conference_conference_theme`.`theme_id`)
# ) AS `c_count`,
# `theme_theme_translation`.`name` as `name`
# FROM
# `theme_theme`
# GROUP BY `theme_theme`.`id`
# ORDER BY NULL
# """
## 2-й рабочий способ (с заполнением перевода)
## аттрибут перевода 'name' присвоен на 'name_t', чтобы не ругалось на неправильно заполненый перевод
# theme_sql = \
# """
# SELECT
# `theme_theme_translation`.`name` AS `name_t`,
# `theme_theme_translation`.`master_id` AS `id`,
# (
# SELECT COUNT(`exposition_exposition_theme`.`exposition_id`)
# FROM `exposition_exposition_theme`
# WHERE (`theme_theme_translation`.`master_id` = `exposition_exposition_theme`.`theme_id`)
# ) AS `e_count`,
# (
# SELECT COUNT(`conference_conference_theme`.`conference_id`)
# FROM `conference_conference_theme`
# WHERE (`theme_theme_translation`.`master_id` = `conference_conference_theme`.`theme_id`)
# ) AS `c_count`
# FROM
# `theme_theme_translation`
# WHERE (`theme_theme_translation`.`language_code` = 'ru')
# GROUP BY `theme_theme_translation`.`name`
# ORDER BY NULL
# """
# qs = Theme.objects.raw(theme_sql)
## 3-й рабочий способ (с родным заполением перевода)
## в ходе поиска, был найден и 4-й рабочий способ используя RawSQL, но он для Django >= 1.8
## https://docs.djangoproject.com/en/1.9/ref/models/expressions/#raw-sql-expressions
## from django.db.models.expressions import RawSQL
extra_themes_expo_count = '''
SELECT COUNT(`exposition_exposition_theme`.`exposition_id`)
FROM `exposition_exposition_theme`
WHERE (`theme_theme`.`id` = `exposition_exposition_theme`.`theme_id`)
'''
extra_themes_conf_count = '''
SELECT COUNT(`conference_conference_theme`.`conference_id`)
FROM `conference_conference_theme`
WHERE (`theme_theme`.`id` = `conference_conference_theme`.`theme_id`)
'''
extra_themes_select = {
'e_count': extra_themes_expo_count,
'c_count': extra_themes_conf_count,
}
themes = Theme.objects.language('ru').extra(select=extra_themes_select)
class FilterForm(forms.Form):
TYPES = EnumChoices(
EXPO=(1, _(u'Выставки')),
CONF=(2, _(_(u'Конференции'))),
)
model = forms.TypedMultipleChoiceField(label=_(u'Тип события'), coerce=int, choices=TYPES, required=False, widget=forms.CheckboxSelectMultiple())
theme = CountModelMultipleChoiceField(label=_(u'Тематики'),
queryset=themes,
required=False, widget=forms.CheckboxSelectMultiple())
# tag = CountModelMultipleChoiceField(label=_(u'Теги'),
# queryset=Tag.active.all()\
# .annotate(e_count=Count('exposition_tags'), c_count=Count('conference_tags')),
# required=False, widget=forms.CheckboxSelectMultiple())
def get_models(self):
val = self.cleaned_data.get('model')
models = []
if val:
if self.TYPES.EXPO in val:
models.append(Exposition)
if self.TYPES.CONF in val:
models.append(Conference)
else:
models = [Conference, Exposition]
return models
def filter(self):
qs = self.default_filter(self.get_models())
d = self.cleaned_data
if d.get('theme'):
qs = qs.filter(theme__in=d.get('theme'))
if d.get('tag'):
qs = qs.filter(tag__in=d.get('tag'))
return qs
def default_filter(self, models=None):
qs = RelatedSearchQuerySet().models(Exposition, Conference).load_all()
models = models or [Exposition, Conference]
for model in models:
qs = qs.load_all_queryset(model, model.enable.all())
return qs