Browse Source

isola viewset do drf anteriores a api e define filterset para sessaoplenaria

pull/2550/head
Leandro Roberto 6 years ago
parent
commit
6b49e08d6e
  1. 230
      sapl/api/deprecated.py
  2. 270
      sapl/api/forms.py
  3. 6
      sapl/api/serializers.py
  4. 80
      sapl/api/views.py

230
sapl/api/deprecated.py

@ -1,11 +1,20 @@
import logging
import logging import logging
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db.models import Q from django.db.models import Q
from django.db.models import Q
from django.forms.fields import CharField, MultiValueField
from django.forms.widgets import MultiWidget, TextInput
from django.http import Http404 from django.http import Http404
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from django_filters.filters import CharFilter, ModelChoiceFilter, DateFilter
from django_filters.rest_framework.backends import DjangoFilterBackend from django_filters.rest_framework.backends import DjangoFilterBackend
from django_filters.rest_framework.filterset import FilterSet
from rest_framework import serializers
from rest_framework import serializers from rest_framework import serializers
from rest_framework.generics import ListAPIView from rest_framework.generics import ListAPIView
from rest_framework.mixins import ListModelMixin, RetrieveModelMixin from rest_framework.mixins import ListModelMixin, RetrieveModelMixin
@ -13,14 +22,231 @@ from rest_framework.permissions import (IsAuthenticated,
IsAuthenticatedOrReadOnly, AllowAny) IsAuthenticatedOrReadOnly, AllowAny)
from rest_framework.viewsets import GenericViewSet from rest_framework.viewsets import GenericViewSet
from sapl.api.forms import (AutorChoiceFilterSet, AutoresPossiveisFilterSet,
AutorSearchForFieldFilterSet)
from sapl.api.serializers import ModelChoiceSerializer, AutorSerializer,\ from sapl.api.serializers import ModelChoiceSerializer, AutorSerializer,\
ChoiceSerializer ChoiceSerializer
from sapl.base.models import TipoAutor, Autor, CasaLegislativa from sapl.base.models import TipoAutor, Autor, CasaLegislativa
from sapl.materia.models import MateriaLegislativa from sapl.materia.models import MateriaLegislativa
from sapl.parlamentares.models import Legislatura
from sapl.sessao.models import SessaoPlenaria, OrdemDia from sapl.sessao.models import SessaoPlenaria, OrdemDia
from sapl.utils import SaplGenericRelation from sapl.utils import SaplGenericRelation
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):
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(CharFilter):
field_class = SearchForFieldField
class AutorChoiceFilterSet(SaplGenericRelationSearchFilterSet):
q = CharFilter(method='filter_q')
tipo = ModelChoiceFilter(queryset=TipoAutor.objects.all())
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):
try:
self.logger.debug(
"Tentando obter TipoAutor correspondente à pk {}.".format(value))
tipo = TipoAutor.objects.get(pk=value)
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)
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
class AutorChoiceSerializer(ModelChoiceSerializer): class AutorChoiceSerializer(ModelChoiceSerializer):

270
sapl/api/forms.py

@ -1,231 +1,65 @@
import logging from django.db.models.fields.files import FileField
from django.template.defaultfilters import capfirst
from django.db.models import Q import django_filters
from django.forms.fields import CharField, MultiValueField from django_filters.filters import CharFilter, NumberFilter
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_filters.rest_framework.filterset import FilterSet from django_filters.rest_framework.filterset import FilterSet
from rest_framework import serializers from django_filters.utils import resolve_field
from sapl.sessao.models import SessaoPlenaria
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):
def decompress(self, value):
if value is None:
return [None, None]
return value
def __init__(self, attrs=None): class SaplFilterSetMixin(FilterSet):
widgets = (TextInput, TextInput)
MultiWidget.__init__(self, widgets, attrs)
o = CharFilter(method='filter_o')
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())
class Meta: class Meta:
model = Autor fields = '__all__'
fields = ['q', filter_overrides = {
'tipo', FileField: {
'nome', ] 'filter_class': django_filters.CharFilter,
'extra': lambda f: {
def filter_q(self, queryset, name, value): 'lookup_expr': 'exact',
return super().filter_q( },
queryset, name, value).distinct('nome').order_by('nome') },
}
class AutorSearchForFieldFilterSet(AutorChoiceFilterSet): def filter_o(self, queryset, name, value):
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):
try: try:
self.logger.debug( return queryset.order_by(
"Tentando obter TipoAutor correspondente à pk {}.".format(value)) *map(str.strip, value.split(',')))
tipo = TipoAutor.objects.get(pk=value)
except: except:
self.logger.error("TipoAutor(pk={}) inexistente.".format(value)) return queryset
raise serializers.ValidationError(_('Tipo de Autor inexistente.'))
@classmethod
qs = queryset.filter(tipo=tipo) def filter_for_field(cls, f, name, lookup_expr='exact'):
# Redefine método estático para ignorar filtro para
return qs # fields que não possuam lookup_expr informado
f, lookup_type = resolve_field(f, lookup_expr)
@property
def qs(self): default = {
qs = super().qs 'field_name': name,
'label': capfirst(f.verbose_name),
data_relativa = self.form.cleaned_data['data_relativa'] \ 'lookup_expr': lookup_expr
if 'data_relativa' in self.form.cleaned_data else None }
tipo = self.form.cleaned_data['tipo'] \ filter_class, params = cls.filter_for_lookup(
if 'tipo' in self.form.cleaned_data else None f, lookup_type)
default.update(params)
if not tipo: if filter_class is not None:
return qs return filter_class(**default)
return None
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)
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): class SessaoPlenariaFilterSet(SaplFilterSetMixin):
return queryset.filter( year = NumberFilter(method='filter_year')
Q(frente_set__data_extincao__isnull=True) | month = NumberFilter(method='filter_month')
Q(frente_set__data_extincao__gte=data_relativa),
frente_set__data_criacao__lte=data_relativa)
def filter_bancada(self, queryset, data_relativa): class Meta(SaplFilterSetMixin.Meta):
return queryset.filter( model = SessaoPlenaria
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): def filter_year(self, queryset, name, value):
return queryset.filter( qs = queryset.filter(data_inicio__year=value)
Q(bloco_set__data_extincao__isnull=True) | return qs
Q(bloco_set__data_extincao__gte=data_relativa),
bloco_set__data_criacao__lte=data_relativa)
def filter_orgao(self, queryset, data_relativa): def filter_month(self, queryset, name, value):
# na implementação, não havia regras a implementar para orgao qs = queryset.filter(data_inicio__month=value)
return queryset return qs

6
sapl/api/serializers.py

@ -1,9 +1,15 @@
from django.conf import settings from django.conf import settings
from rest_framework import serializers from rest_framework import serializers
from rest_framework.relations import StringRelatedField
from sapl.base.models import Autor, CasaLegislativa from sapl.base.models import Autor, CasaLegislativa
class IntRelatedField(StringRelatedField):
def to_representation(self, value):
return int(value)
class ChoiceSerializer(serializers.Serializer): class ChoiceSerializer(serializers.Serializer):
value = serializers.SerializerMethodField() value = serializers.SerializerMethodField()
text = serializers.SerializerMethodField() text = serializers.SerializerMethodField()

80
sapl/api/views.py

@ -18,11 +18,27 @@ from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from sapl.api.forms import SaplFilterSetMixin
from sapl.api.permissions import SaplModelPermissions from sapl.api.permissions import SaplModelPermissions
from sapl.api.serializers import ChoiceSerializer
from sapl.base.models import Autor, AppConfig, DOC_ADM_OSTENSIVO from sapl.base.models import Autor, AppConfig, DOC_ADM_OSTENSIVO
from sapl.materia.models import Proposicao from sapl.materia.models import Proposicao
from sapl.parlamentares.models import Parlamentar from sapl.parlamentares.models import Parlamentar
from sapl.utils import models_with_gr_for_model from sapl.utils import models_with_gr_for_model, choice_anos_com_sessaoplenaria
class BusinessRulesNotImplementedMixin:
def create(self, request, *args, **kwargs):
raise Exception(_("POST Create não implementado"))
def put(self, request, *args, **kwargs):
raise Exception(_("PUT Update não implementado"))
def patch(self, request, *args, **kwargs):
raise Exception(_("PATCH Partial Update não implementado"))
def delete(self, request, *args, **kwargs):
raise Exception(_("DELETE Delete não implementado"))
class SaplApiViewSetConstrutor(ModelViewSet): class SaplApiViewSetConstrutor(ModelViewSet):
@ -74,47 +90,9 @@ class SaplApiViewSetConstrutor(ModelViewSet):
# Define uma classe padrão para filtro caso não tenha sido # Define uma classe padrão para filtro caso não tenha sido
# criada a classe sapl.api.forms.{model}FilterSet # criada a classe sapl.api.forms.{model}FilterSet
class SaplFilterSet(FilterSet): class SaplFilterSet(SaplFilterSetMixin):
class Meta(SaplFilterSetMixin.Meta):
o = CharFilter(method='filter_o')
class Meta:
model = _model model = _model
fields = '__all__'
filter_overrides = {
FileField: {
'filter_class': django_filters.CharFilter,
'extra': lambda f: {
'lookup_expr': 'exact',
},
},
}
def filter_o(self, queryset, name, value):
try:
return queryset.order_by(
*map(str.strip, value.split(',')))
except:
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
# Define uma classe padrão ModelViewSet de DRF # Define uma classe padrão ModelViewSet de DRF
class ModelSaplViewSet(cls): class ModelSaplViewSet(cls):
@ -420,7 +398,8 @@ class _DocumentoAcessorioAdministrativoViewSet(
class _TramitacaoAdministrativoViewSet( class _TramitacaoAdministrativoViewSet(
SaplSetViews['protocoloadm']['tramitacaoadministrativo']): SaplSetViews['protocoloadm']['tramitacaoadministrativo'],
BusinessRulesNotImplementedMixin):
# TODO: Implementar regras de manutenção das tramitações de docs adms # TODO: Implementar regras de manutenção das tramitações de docs adms
permission_classes = ( permission_classes = (
@ -433,17 +412,16 @@ class _TramitacaoAdministrativoViewSet(
qs = qs.exclude(documento__restrito=True) qs = qs.exclude(documento__restrito=True)
return qs return qs
def create(self, request, *args, **kwargs):
raise Exception(_("POST Create não implementado"))
def put(self, request, *args, **kwargs): class _SessaoPlenariaViewSet(
raise Exception(_("PUT Update não implementado")) SaplSetViews['sessao']['sessaoplenaria']):
def patch(self, request, *args, **kwargs): @action(detail=False)
raise Exception(_("PATCH Partial Update não implementado")) def years(self, request, *args, **kwargs):
years = choice_anos_com_sessaoplenaria()
def delete(self, request, *args, **kwargs): serializer = ChoiceSerializer(years, many=True)
raise Exception(_("DELETE Delete não implementado")) return Response(serializer.data)
SaplSetViews['base']['autor'] = _AutorViewSet.build_class_with_actions() SaplSetViews['base']['autor'] = _AutorViewSet.build_class_with_actions()
@ -455,3 +433,5 @@ SaplSetViews['parlamentares']['parlamentar'] = _ParlamentarViewSet
SaplSetViews['protocoloadm']['documentoadministrativo'] = _DocumentoAdministrativoViewSet SaplSetViews['protocoloadm']['documentoadministrativo'] = _DocumentoAdministrativoViewSet
SaplSetViews['protocoloadm']['documentoacessorioadministrativo'] = _DocumentoAcessorioAdministrativoViewSet SaplSetViews['protocoloadm']['documentoacessorioadministrativo'] = _DocumentoAcessorioAdministrativoViewSet
SaplSetViews['protocoloadm']['tramitacaoadministrativo'] = _TramitacaoAdministrativoViewSet SaplSetViews['protocoloadm']['tramitacaoadministrativo'] = _TramitacaoAdministrativoViewSet
SaplSetViews['sessao']['sessaoplenaria'] = _SessaoPlenariaViewSet

Loading…
Cancel
Save