|
|
@ -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 |
|
|
|
return queryset |
|
|
|
|
|
|
|
@property |
|
|
|
def qs(self): |
|
|
|
qs = super().qs |
|
|
|
@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 |
|
|
|
|
|
|
|
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 |
|
|
|
class SessaoPlenariaFilterSet(SaplFilterSetMixin): |
|
|
|
year = NumberFilter(method='filter_year') |
|
|
|
month = NumberFilter(method='filter_month') |
|
|
|
|
|
|
|
if not tipo: |
|
|
|
return qs |
|
|
|
class Meta(SaplFilterSetMixin.Meta): |
|
|
|
model = SessaoPlenaria |
|
|
|
|
|
|
|
tipo = TipoAutor.objects.get(pk=tipo) |
|
|
|
if not tipo.content_type: |
|
|
|
def filter_year(self, queryset, name, value): |
|
|
|
qs = queryset.filter(data_inicio__year=value) |
|
|
|
return qs |
|
|
|
|
|
|
|
filter_for_model = 'filter_%s' % tipo.content_type.model |
|
|
|
|
|
|
|
if not hasattr(self, filter_for_model): |
|
|
|
def filter_month(self, queryset, name, value): |
|
|
|
qs = queryset.filter(data_inicio__month=value) |
|
|
|
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) |
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
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) |
|
|
|
|
|
|
|
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_orgao(self, queryset, data_relativa): |
|
|
|
# na implementação, não havia regras a implementar para orgao |
|
|
|
return queryset |
|
|
|