diff --git a/sapl/api/forms.py b/sapl/api/forms.py index 4609273e4..afa9190f4 100644 --- a/sapl/api/forms.py +++ b/sapl/api/forms.py @@ -1,5 +1,8 @@ from django.db.models import Q +from django.forms.fields import MultiValueField, CharField +from django.forms.widgets import TextInput, MultiWidget from django_filters.filters import MethodFilter, ModelChoiceFilter +from rest_framework.compat import django_filters from rest_framework.filters import FilterSet from sapl.base.models import Autor, TipoAutor @@ -49,6 +52,37 @@ class SaplGenericRelationSearchFilterSet(FilterSet): return queryset +class SearchForFieldWidget(MultiWidget): + + 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 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(django_filters.filters.MethodFilter): + field_class = SearchForFieldField + + class AutorChoiceFilterSet(SaplGenericRelationSearchFilterSet): q = MethodFilter() tipo = ModelChoiceFilter(queryset=TipoAutor.objects.all()) @@ -62,3 +96,22 @@ class AutorChoiceFilterSet(SaplGenericRelationSearchFilterSet): def filter_q(self, queryset, value): return SaplGenericRelationSearchFilterSet.filter_q( self, queryset, value).distinct('nome').order_by('nome') + + +class AutorSearchForFieldFilterSet(AutorChoiceFilterSet): + q = SearchForFieldFilter() + + class Meta(AutorChoiceFilterSet.Meta): + pass + + def filter_q(self, queryset, 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') diff --git a/sapl/api/views.py b/sapl/api/views.py index 4a8341c52..eb1364bf7 100644 --- a/sapl/api/views.py +++ b/sapl/api/views.py @@ -10,7 +10,7 @@ from rest_framework.permissions import (IsAuthenticated, AllowAny) from rest_framework.viewsets import GenericViewSet, ModelViewSet -from sapl.api.forms import AutorChoiceFilterSet +from sapl.api.forms import AutorChoiceFilterSet, AutorSearchForFieldFilterSet from sapl.api.serializers import (AutorChoiceSerializer, AutorSerializer, ChoiceSerializer, MateriaLegislativaSerializer, @@ -79,7 +79,57 @@ class AutorListView(ListAPIView): o django-filter é desativado e a busca é feita no model do ContentType associado ao tipo. - Outros campos + - q_0 / q_1 - q_0 faz o código ignorar "q"... + + q_0 -> campos lookup a serem filtrados em qualquer Model + que implemente SaplGenericRelation + q_1 -> o valor que será pesquisado no lookup de q_0 + + q_0 e q_1 podem ser separados por ","... isso dará a + possibilidade de filtrar mais de um campo. + + + http://localhost:8000 + /api/autor?tr=1&q_0=parlamentar_set__ativo&q_1=False + /api/autor?tr=1&q_0=parlamentar_set__ativo&q_1=True + /api/autor?tr=3&q_0=parlamentar_set__ativo&q_1=False + /api/autor?tr=3&q_0=parlamentar_set__ativo&q_1=True + + http://localhost:8000 + /api/autor?tr=1 + &q_0=parlamentar_set__nome_completo__icontains, + parlamentar_set__ativo + &q_1=Carvalho,False + /api/autor?tr=1 + &q_0=parlamentar_set__nome_completo__icontains, + parlamentar_set__ativo + &q_1=Carvalho,True + /api/autor?tr=3 + &q_0=parlamentar_set__nome_completo__icontains, + parlamentar_set__ativo + &q_1=Carvalho,False + /api/autor?tr=3 + &q_0=parlamentar_set__nome_completo__icontains, + parlamentar_set__ativo + &q_1=Carvalho,True + + + não importa o campo que vc passe de qualquer dos Models + ligados... é possível ver que models são esses, + na ocasião do commit deste texto, executando: + In [6]: from sapl.utils import models_with_gr_for_model + + In [7]: models_with_gr_for_model(Autor) + Out[7]: + [sapl.parlamentares.models.Parlamentar, + sapl.parlamentares.models.Frente, + sapl.comissoes.models.Comissao, + sapl.materia.models.Orgao, + sapl.sessao.models.Bancada, + sapl.sessao.models.Bloco] + + qualquer atributo destes models podem ser passados + para busca """ TR_AUTOR_CHOICE_SERIALIZER = 1 @@ -125,6 +175,9 @@ class AutorListView(ListAPIView): self.serializer_class = AutorSerializer self.permission_classes = (IsAuthenticated,) + if self.filter_class and 'q_0' in request.GET: + self.filter_class = AutorSearchForFieldFilterSet + return ListAPIView.get(self, request, *args, **kwargs) def get_queryset(self): @@ -207,6 +260,7 @@ class MateriaLegislativaViewSet(ListModelMixin, filter_backends = (DjangoFilterBackend,) filter_fields = ('numero', 'ano', 'tipo', ) + class SessaoPlenariaViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet): diff --git a/sapl/utils.py b/sapl/utils.py index 4873d3519..618a3f4f8 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -392,92 +392,6 @@ def intervalos_tem_intersecao(a_inicio, a_fim, b_inicio, b_fim): return maior_inicio <= menor_fim -""" -def permissoes(nome_grupo, app_label): - lista_permissoes = [] - try: - perms = list(Permission.objects.filter( - group__name=nome_grupo)) - for p in perms: - lista_permissoes.append('%s.%s' % (app_label, p.codename)) - except: - pass - return set(lista_permissoes) - - -def permission_required_for_app(app_label, login_url=None, - raise_exception=False): - - Decorator for views that checks whether a user has a particular permission - enabled, redirecting to the log-in page if necessary. - If the raise_exception parameter is given the PermissionDenied exception - is raised. - - def check_perms(user): - if user.has_module_perms(app_label): - return True - # In case the 403 handler should be called raise the exception - if raise_exception: - raise PermissionDenied - # As the last resort, show the login form - return False - return user_passes_test(check_perms, login_url=login_url) - -def permissoes_materia(): - return permissoes('Operador de Matéria', 'materia') - - -def permissoes_comissoes(): - return permissoes('Operador de Comissões', 'comissoes') - - -def permissoes_norma(): - return permissoes('Operador de Norma Jurídica', 'norma') - - -def permissoes_protocoloadm(): - return permissoes('Operador de Protocolo Administrativo', 'protocoloadm') - - -def permissoes_adm(): - return permissoes('Operador Administrativo', 'protocoloadm') - - -def permissoes_sessao(): - return permissoes('Operador de Sessão Plenária', 'sessao') - - -def permissoes_painel(): - return permissoes('Operador de Painel Eletrônico', 'painel') - - -def permissoes_autor(): - return permissoes('Autor', 'materia') - - -def permissoes_parlamentares(): - lista_permissoes = [] - try: - cts = ContentType.objects.filter(app_label='parlamentares') - perms_parlamentares = list(Permission.objects.filter( - content_type__in=cts)) - for p in perms_parlamentares: - lista_permissoes.append('parlamentares.' + p.codename) - except: - pass - return set(lista_permissoes) - - -def permissao_tb_aux(self): - u = self.request.user - if u.groups.filter(name='Operador Geral').exists() or u.is_superuser: - return True - else: - return False - -""" - - class MateriaPesquisaOrderingFilter(django_filters.OrderingFilter): choices = (