mirror of https://github.com/interlegis/sapl.git
Leandro Roberto
6 years ago
4 changed files with 316 additions and 270 deletions
@ -1,231 +1,65 @@ |
|||
import logging |
|||
|
|||
from django.db.models import Q |
|||
from django.forms.fields import CharField, MultiValueField |
|||
from django.forms.widgets import MultiWidget, TextInput |
|||
from django.utils import timezone |
|||
from django.utils.translation import ugettext_lazy as _ |
|||
from django_filters.filters import CharFilter, ModelChoiceFilter, DateFilter |
|||
from django.db.models.fields.files import FileField |
|||
from django.template.defaultfilters import capfirst |
|||
import django_filters |
|||
from django_filters.filters import CharFilter, NumberFilter |
|||
from django_filters.rest_framework.filterset import FilterSet |
|||
from rest_framework import serializers |
|||
|
|||
from sapl.base.models import Autor, TipoAutor |
|||
from sapl.parlamentares.models import Legislatura |
|||
from sapl.utils import generic_relations_for_model |
|||
|
|||
|
|||
class SaplGenericRelationSearchFilterSet(FilterSet): |
|||
q = CharFilter(method='filter_q') |
|||
|
|||
def filter_q(self, queryset, name, value): |
|||
|
|||
query = value.split(' ') |
|||
if query: |
|||
q = Q() |
|||
for qtext in query: |
|||
if not qtext: |
|||
continue |
|||
q_fs = Q(nome__icontains=qtext) |
|||
|
|||
order_by = [] |
|||
|
|||
for gr in generic_relations_for_model(self._meta.model): |
|||
sgr = gr[1] |
|||
for item in sgr: |
|||
if item.related_model != self._meta.model: |
|||
|
|||
continue |
|||
flag_order_by = True |
|||
for field in item.fields_search: |
|||
if flag_order_by: |
|||
flag_order_by = False |
|||
order_by.append('%s__%s' % ( |
|||
item.related_query_name(), |
|||
field[0]) |
|||
) |
|||
# if len(field) == 3 and field[2](qtext) is not |
|||
# None: |
|||
q_fs = q_fs | Q(**{'%s__%s%s' % ( |
|||
item.related_query_name(), |
|||
field[0], |
|||
field[1]): qtext if len(field) == 2 |
|||
else field[2](qtext)}) |
|||
|
|||
q = q & q_fs |
|||
|
|||
if q: |
|||
queryset = queryset.filter(q).order_by(*order_by) |
|||
|
|||
return queryset |
|||
|
|||
|
|||
class SearchForFieldWidget(MultiWidget): |
|||
from django_filters.utils import resolve_field |
|||
from sapl.sessao.models import SessaoPlenaria |
|||
|
|||
def decompress(self, value): |
|||
if value is None: |
|||
return [None, None] |
|||
return value |
|||
|
|||
def __init__(self, attrs=None): |
|||
widgets = (TextInput, TextInput) |
|||
MultiWidget.__init__(self, widgets, attrs) |
|||
class SaplFilterSetMixin(FilterSet): |
|||
|
|||
|
|||
class SearchForFieldField(MultiValueField): |
|||
widget = SearchForFieldWidget |
|||
|
|||
def __init__(self, *args, **kwargs): |
|||
fields = ( |
|||
CharField(), |
|||
CharField()) |
|||
super(SearchForFieldField, self).__init__(fields, *args, **kwargs) |
|||
|
|||
def compress(self, parameters): |
|||
if parameters: |
|||
return parameters |
|||
return None |
|||
|
|||
|
|||
class SearchForFieldFilter(CharFilter): |
|||
field_class = SearchForFieldField |
|||
|
|||
|
|||
class AutorChoiceFilterSet(SaplGenericRelationSearchFilterSet): |
|||
q = CharFilter(method='filter_q') |
|||
tipo = ModelChoiceFilter(queryset=TipoAutor.objects.all()) |
|||
o = CharFilter(method='filter_o') |
|||
|
|||
class Meta: |
|||
model = Autor |
|||
fields = ['q', |
|||
'tipo', |
|||
'nome', ] |
|||
|
|||
def filter_q(self, queryset, name, value): |
|||
return super().filter_q( |
|||
queryset, name, value).distinct('nome').order_by('nome') |
|||
|
|||
|
|||
class AutorSearchForFieldFilterSet(AutorChoiceFilterSet): |
|||
q = SearchForFieldFilter(method='filter_q') |
|||
|
|||
class Meta(AutorChoiceFilterSet.Meta): |
|||
pass |
|||
|
|||
def filter_q(self, queryset, name, value): |
|||
|
|||
value[0] = value[0].split(',') |
|||
value[1] = value[1].split(',') |
|||
|
|||
params = {} |
|||
for key, v in list(zip(value[0], value[1])): |
|||
if v in ['True', 'False']: |
|||
v = '1' if v == 'True' else '0' |
|||
params[key] = v |
|||
return queryset.filter(**params).distinct('nome').order_by('nome') |
|||
|
|||
|
|||
class AutoresPossiveisFilterSet(FilterSet): |
|||
logger = logging.getLogger(__name__) |
|||
data_relativa = DateFilter(method='filter_data_relativa') |
|||
tipo = CharFilter(method='filter_tipo') |
|||
|
|||
class Meta: |
|||
model = Autor |
|||
fields = ['data_relativa', 'tipo', ] |
|||
|
|||
def filter_data_relativa(self, queryset, name, value): |
|||
return queryset |
|||
|
|||
def filter_tipo(self, queryset, name, value): |
|||
|
|||
fields = '__all__' |
|||
filter_overrides = { |
|||
FileField: { |
|||
'filter_class': django_filters.CharFilter, |
|||
'extra': lambda f: { |
|||
'lookup_expr': 'exact', |
|||
}, |
|||
}, |
|||
} |
|||
|
|||
def filter_o(self, queryset, name, value): |
|||
try: |
|||
self.logger.debug( |
|||
"Tentando obter TipoAutor correspondente à pk {}.".format(value)) |
|||
tipo = TipoAutor.objects.get(pk=value) |
|||
return queryset.order_by( |
|||
*map(str.strip, value.split(','))) |
|||
except: |
|||
self.logger.error("TipoAutor(pk={}) inexistente.".format(value)) |
|||
raise serializers.ValidationError(_('Tipo de Autor inexistente.')) |
|||
|
|||
qs = queryset.filter(tipo=tipo) |
|||
|
|||
return qs |
|||
|
|||
@property |
|||
def qs(self): |
|||
qs = super().qs |
|||
|
|||
data_relativa = self.form.cleaned_data['data_relativa'] \ |
|||
if 'data_relativa' in self.form.cleaned_data else None |
|||
|
|||
tipo = self.form.cleaned_data['tipo'] \ |
|||
if 'tipo' in self.form.cleaned_data else None |
|||
|
|||
if not tipo: |
|||
return qs |
|||
|
|||
tipo = TipoAutor.objects.get(pk=tipo) |
|||
if not tipo.content_type: |
|||
return qs |
|||
|
|||
filter_for_model = 'filter_%s' % tipo.content_type.model |
|||
|
|||
if not hasattr(self, filter_for_model): |
|||
return qs |
|||
|
|||
if not data_relativa: |
|||
data_relativa = timezone.now() |
|||
|
|||
return getattr(self, filter_for_model)(qs, data_relativa).distinct() |
|||
|
|||
def filter_parlamentar(self, queryset, data_relativa): |
|||
# não leva em conta afastamentos |
|||
legislatura_relativa = Legislatura.objects.filter( |
|||
data_inicio__lte=data_relativa, |
|||
data_fim__gte=data_relativa).first() |
|||
|
|||
q = Q( |
|||
parlamentar_set__mandato__data_inicio_mandato__lte=data_relativa, |
|||
parlamentar_set__mandato__data_fim_mandato__isnull=True) | Q( |
|||
parlamentar_set__mandato__data_inicio_mandato__lte=data_relativa, |
|||
parlamentar_set__mandato__data_fim_mandato__gte=data_relativa) |
|||
|
|||
if legislatura_relativa.atual(): |
|||
q = q & Q(parlamentar_set__ativo=True) |
|||
|
|||
return queryset.filter(q) |
|||
return queryset |
|||
|
|||
@classmethod |
|||
def filter_for_field(cls, f, name, lookup_expr='exact'): |
|||
# Redefine método estático para ignorar filtro para |
|||
# fields que não possuam lookup_expr informado |
|||
f, lookup_type = resolve_field(f, lookup_expr) |
|||
|
|||
default = { |
|||
'field_name': name, |
|||
'label': capfirst(f.verbose_name), |
|||
'lookup_expr': lookup_expr |
|||
} |
|||
|
|||
filter_class, params = cls.filter_for_lookup( |
|||
f, lookup_type) |
|||
default.update(params) |
|||
if filter_class is not None: |
|||
return filter_class(**default) |
|||
return None |
|||
|
|||
def filter_comissao(self, queryset, data_relativa): |
|||
return queryset.filter( |
|||
Q(comissao_set__data_extincao__isnull=True, |
|||
comissao_set__data_fim_comissao__isnull=True) | |
|||
Q(comissao_set__data_extincao__gte=data_relativa, |
|||
comissao_set__data_fim_comissao__isnull=True) | |
|||
Q(comissao_set__data_extincao__gte=data_relativa, |
|||
comissao_set__data_fim_comissao__isnull=True) | |
|||
Q(comissao_set__data_extincao__isnull=True, |
|||
comissao_set__data_fim_comissao__gte=data_relativa) | |
|||
Q(comissao_set__data_extincao__gte=data_relativa, |
|||
comissao_set__data_fim_comissao__gte=data_relativa), |
|||
comissao_set__data_criacao__lte=data_relativa) |
|||
|
|||
def filter_frente(self, queryset, data_relativa): |
|||
return queryset.filter( |
|||
Q(frente_set__data_extincao__isnull=True) | |
|||
Q(frente_set__data_extincao__gte=data_relativa), |
|||
frente_set__data_criacao__lte=data_relativa) |
|||
class SessaoPlenariaFilterSet(SaplFilterSetMixin): |
|||
year = NumberFilter(method='filter_year') |
|||
month = NumberFilter(method='filter_month') |
|||
|
|||
def filter_bancada(self, queryset, data_relativa): |
|||
return queryset.filter( |
|||
Q(bancada_set__data_extincao__isnull=True) | |
|||
Q(bancada_set__data_extincao__gte=data_relativa), |
|||
bancada_set__data_criacao__lte=data_relativa) |
|||
class Meta(SaplFilterSetMixin.Meta): |
|||
model = SessaoPlenaria |
|||
|
|||
def filter_bloco(self, queryset, data_relativa): |
|||
return queryset.filter( |
|||
Q(bloco_set__data_extincao__isnull=True) | |
|||
Q(bloco_set__data_extincao__gte=data_relativa), |
|||
bloco_set__data_criacao__lte=data_relativa) |
|||
def filter_year(self, queryset, name, value): |
|||
qs = queryset.filter(data_inicio__year=value) |
|||
return qs |
|||
|
|||
def filter_orgao(self, queryset, data_relativa): |
|||
# na implementação, não havia regras a implementar para orgao |
|||
return queryset |
|||
def filter_month(self, queryset, name, value): |
|||
qs = queryset.filter(data_inicio__month=value) |
|||
return qs |
|||
|
Loading…
Reference in new issue