diff --git a/events/forms.py b/events/forms.py index 84a3f8bb..4daacc2a 100644 --- a/events/forms.py +++ b/events/forms.py @@ -11,9 +11,8 @@ from django.utils.translation import get_language, 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, Q +from django.db.models import Count, Sum, Q, ForeignKey, ManyToManyField from django.core.exceptions import ValidationError - from haystack.query import SearchQuerySet, RelatedSearchQuerySet from functions.model_utils import EnumChoices @@ -267,10 +266,11 @@ class FilterForm(forms.Form): def recalculate_choices(self): print(self._is_valid) if self._is_valid: - for field, val in self.lookup_kwargs.iteritems(): + for field in ['theme', 'tag', 'city', 'country']: field_qs = self.default_filter(load_all=False) field_lookup_kwargs = self.lookup_kwargs.copy() - del field_lookup_kwargs[field] + if field in field_lookup_kwargs.keys(): + del field_lookup_kwargs[field] # if not field_lookup_kwargs: # continue # field_qs = (x.id.split('.')[1:] for x in self.filter(qs=field_qs, lookup_kwargs=field_lookup_kwargs) if x.id) @@ -279,8 +279,6 @@ class FilterForm(forms.Form): self.fields[field].queryset = self.fields[field].queryset.extra( select=self.make_count_select(field, field_lookup_kwargs)).values('pk', 'name', 'count') print(self.fields[field].queryset.query) - # self.make_count_select(field, field_lookup_kwargs) - # print(field_qs) for field in self.fields: field = self.fields[field] @@ -292,7 +290,11 @@ class FilterForm(forms.Form): print('looking {} {}'.format(field, lookup_kwargs)) for model in self.models: _field, _model, direct, m2m = model._meta.get_field_by_name(field) - if m2m: + joins = [] + where = [] + group_by = '' + # ManyToManyField + if m2m and direct and isinstance(_field, ManyToManyField): _field format_kwargs = { 'm2m_db_table': _field.m2m_db_table(), @@ -305,14 +307,28 @@ class FilterForm(forms.Form): select = \ '''SELECT COUNT(`{m2m_db_table}`.`{m2m_column_name}`) FROM `{m2m_db_table}` INNER JOIN `{db_table}` ON (`{m2m_db_table}`.`{m2m_column_name}` = `{db_table}`.`id`) '''\ .format(**format_kwargs) - joins = [] - where = [ - ''' (`{m2m_rel_to_table}_translation`.`master_id` = `{m2m_db_table}`.`{m2m_reverse_name}`) '''.format(**format_kwargs) - ] - - for l_field, lookups in lookup_kwargs.iteritems(): - _l_field, l_model, _direct, _m2m = model._meta.get_field_by_name(l_field) - values = lookups.values()[0] + where.append( + ''' (`{m2m_rel_to_table}_translation`.`master_id` = `{m2m_db_table}`.`{m2m_reverse_name}`) '''.format(**format_kwargs) + ) + + # ForeignKey + elif not m2m and direct and isinstance(_field, ForeignKey): + format_kwargs = { + 'attname': _field.column, + 'db_table': model._meta.db_table, + 'rel_db_table': _field.rel.to._meta.db_table, + # 'attname': _field.related.field.get_attname(), + } + select = \ + '''SELECT COUNT(`{db_table}`.`id`) FROM `{rel_db_table}` LEFT OUTER JOIN `{db_table}` ON (`{rel_db_table}`.`id` = `{db_table}`.`{attname}`)'''\ + .format(**format_kwargs) + group_by = ''' GROUP BY `{rel_db_table}`.`id` '''.format(**format_kwargs) + + # joins and where lookups + for l_field, lookups in lookup_kwargs.iteritems(): + _l_field, l_model, _direct, _m2m = model._meta.get_field_by_name(l_field) + values = lookups.values()[0] + if _m2m and _direct and isinstance(_l_field, ManyToManyField): _format_kwargs = { 'm2m_db_table': _l_field.m2m_db_table(), 'm2m_column_name': _l_field.m2m_column_name(), @@ -326,7 +342,16 @@ class FilterForm(forms.Form): where.append( '''`{m2m_db_table}`.`{m2m_reverse_name}` IN {ids}'''\ .format(**_format_kwargs)) - count_selects.append(select + ''.join(joins) + ' where ' + ' and '.join(where)) + elif not m2m and _direct and isinstance(_l_field, ForeignKey): + _format_kwargs = { + 'db_table': model._meta.db_table, + 'attname': _l_field.column, + 'ids': tuple(values) if len(values) > 1 else '({})'.format(*values), + } + where.append( + '''`{db_table}`.`{attname}` IN {ids}'''\ + .format(**_format_kwargs)) + count_selects.append(select + ''.join(joins) + ' where ' + ' and '.join(where) + group_by) # case selected # todo @@ -334,8 +359,26 @@ class FilterForm(forms.Form): count = '({}) + ({})'.format(*count_selects) elif len(count_selects) == 1: count = count_selects[0] + else: + return {} return {'count': count} +''' +SELECT + COUNT(`conference_conference`.`id`) AS `count` +FROM + `city_city` + LEFT OUTER JOIN + `conference_conference` ON (`city_city`.`id` = `conference_conference`.`city_id`) + LEFT OUTER JOIN + `conference_conference_tag` ON (`conference_conference`.`id` = `conference_conference_tag`.`conference_id`) +WHERE + `conference_conference_tag`.`tag_id` IN (469 , 832, 366, 922) +GROUP BY `city_city`.`id` +ORDER BY NULL +''' + + ''' SELECT (SELECT