From bed2e052ddbd7aacabedd9cb74d13436aedbaf37 Mon Sep 17 00:00:00 2001 From: Leandro Roberto Date: Mon, 11 Feb 2019 22:55:22 -0200 Subject: [PATCH] =?UTF-8?q?add=20comment=C3=A1rios=20em=20viewset=20deprec?= =?UTF-8?q?ated?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/api/deprecated.py | 326 +++++++++++++++++++++++++++++++++++++++++ sapl/api/urls.py | 36 ++--- sapl/api/views.py | 281 +---------------------------------- 3 files changed, 348 insertions(+), 295 deletions(-) create mode 100644 sapl/api/deprecated.py diff --git a/sapl/api/deprecated.py b/sapl/api/deprecated.py new file mode 100644 index 000000000..48c3db12d --- /dev/null +++ b/sapl/api/deprecated.py @@ -0,0 +1,326 @@ + +import logging + +from django import apps +from django.conf import settings +from django.contrib.contenttypes.models import ContentType +from django.db.models import Q +from django.db.models.fields.files import FileField +from django.http import Http404 +from django.utils.decorators import classonlymethod +from django.utils.text import capfirst +from django.utils.translation import ugettext_lazy as _ +import django_filters +from django_filters.rest_framework.backends import DjangoFilterBackend +from django_filters.rest_framework.filterset import FilterSet +from django_filters.utils import resolve_field +from rest_framework import serializers as rest_serializers +from rest_framework.decorators import list_route, detail_route,\ + permission_classes +from rest_framework.generics import ListAPIView +from rest_framework.mixins import ListModelMixin, RetrieveModelMixin +from rest_framework.permissions import (IsAuthenticated, + IsAuthenticatedOrReadOnly, AllowAny) +from rest_framework.response import Response +from rest_framework.viewsets import GenericViewSet, ModelViewSet + +from sapl.api.forms import (AutorChoiceFilterSet, AutoresPossiveisFilterSet, + AutorSearchForFieldFilterSet) +from sapl.api.permissions import SaplModelPermissions +from sapl.api.serializers import (AutorChoiceSerializer, AutorSerializer, + ChoiceSerializer, + ModelChoiceSerializer, + SessaoPlenariaOldSerializer, + MateriaLegislativaOldSerializer) +from sapl.base.models import TipoAutor, Autor +from sapl.comissoes.models import Comissao +from sapl.materia.models import MateriaLegislativa, Proposicao +from sapl.parlamentares.models import Parlamentar +from sapl.sessao.models import SessaoPlenaria +from sapl.utils import SaplGenericRelation + + +class ModelChoiceView(ListAPIView): + """ + Deprecated + + TODO Migrar para customização na api automática + + """ + + # FIXME aplicar permissão correta de usuário + permission_classes = (IsAuthenticated,) + serializer_class = ModelChoiceSerializer + + def get(self, request, *args, **kwargs): + self.model = ContentType.objects.get_for_id( + self.kwargs['content_type']).model_class() + + pagination = request.GET.get('pagination', '') + + if pagination == 'False': + self.pagination_class = None + + return ListAPIView.get(self, request, *args, **kwargs) + + def get_queryset(self): + return self.model.objects.all() + + +class AutorListView(ListAPIView): + """ + Deprecated + + TODO Migrar para customização na api automática + + Listagem de Autores com filtro para autores já cadastrados + e/ou possíveis autores. + + - tr - tipo do resultado + Prepera Lista de Autores para 2 cenários distintos + + - default = 1 + + = 1 -> para (value, text) usados geralmente + em combobox, radiobox, checkbox, etc com pesquisa básica + de Autores feita pelo django-filter + -> processo usado nas pesquisas, o mais usado. + + + = 3 -> Devolve instancias da classe Autor filtradas pelo + django-filter + + - tipo - chave primária do Tipo de Autor a ser filtrado + + - q - busca textual no nome do Autor ou em fields_search + declarados no field SaplGenericRelation das GenericFks + A busca textual acontece via django-filter com a + variável `tr` igual 1 ou 3. Em caso contrário, + o django-filter é desativado e a busca é feita + no model do ContentType associado ao tipo. + + - q_0 / q_1 - q_0 é opcional e quando usado, 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_parlamentar__icontains, + parlamentar_set__ativo + &q_1=Carvalho,False + /api/autor?tr=1 + &q_0=parlamentar_set__nome_parlamentar__icontains, + parlamentar_set__ativo + &q_1=Carvalho,True + /api/autor?tr=3 + &q_0=parlamentar_set__nome_parlamentar__icontains, + parlamentar_set__ativo + &q_1=Carvalho,False + /api/autor?tr=3 + &q_0=parlamentar_set__nome_parlamentar__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 + """ + logger = logging.getLogger(__name__) + + TR_AUTOR_CHOICE_SERIALIZER = 1 + TR_AUTOR_SERIALIZER = 3 + + permission_classes = (IsAuthenticatedOrReadOnly,) + queryset = Autor.objects.all() + model = Autor + + filter_class = AutorChoiceFilterSet + filter_backends = (DjangoFilterBackend, ) + serializer_class = AutorChoiceSerializer + + @property + def tr(self): + username = self.request.user.username + try: + tr = int(self.request.GET.get + ('tr', AutorListView.TR_AUTOR_CHOICE_SERIALIZER)) + + if tr not in (AutorListView.TR_AUTOR_CHOICE_SERIALIZER, + AutorListView.TR_AUTOR_SERIALIZER): + return AutorListView.TR_AUTOR_CHOICE_SERIALIZER + except Exception as e: + self.logger.error('user=' + username + '. ' + str(e)) + return AutorListView.TR_AUTOR_CHOICE_SERIALIZER + return tr + + def get(self, request, *args, **kwargs): + if self.tr == AutorListView.TR_AUTOR_SERIALIZER: + 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) + + +class AutoresProvaveisListView(ListAPIView): + """ + Deprecated + + TODO Migrar para customização na api automática + """ + + logger = logging.getLogger(__name__) + + permission_classes = (IsAuthenticatedOrReadOnly,) + queryset = Autor.objects.all() + model = Autor + + filter_class = None + filter_backends = [] + serializer_class = ChoiceSerializer + + def get_queryset(self): + + params = {'content_type__isnull': False} + username = self.request.user.username + tipo = '' + try: + tipo = int(self.request.GET.get('tipo', '')) + if tipo: + params['id'] = tipo + except Exception as e: + self.logger.error('user= ' + username + '. ' + str(e)) + pass + + tipos = TipoAutor.objects.filter(**params) + + if not tipos.exists() and tipo: + raise Http404() + + r = [] + for tipo in tipos: + q = self.request.GET.get('q', '').strip() + + model_class = tipo.content_type.model_class() + + fields = list(filter( + lambda field: isinstance(field, SaplGenericRelation) and + field.related_model == Autor, + model_class._meta.get_fields(include_hidden=True))) + + """ + fields - é um array de SaplGenericRelation que deve possuir o + atributo fields_search. Verifique na documentação da classe + a estrutura de fields_search. + """ + + assert len(fields) >= 1, (_( + 'Não foi encontrado em %(model)s um atributo do tipo ' + 'SaplGenericRelation que use o model %(model_autor)s') % { + 'model': model_class._meta.verbose_name, + 'model_autor': Autor._meta.verbose_name}) + + qs = model_class.objects.all() + + q_filter = Q() + if q: + for item in fields: + if item.related_model != Autor: + continue + q_fs = Q() + for field in item.fields_search: + q_fs = q_fs | Q(**{'%s%s' % ( + field[0], + field[1]): q}) + q_filter = q_filter & q_fs + + qs = qs.filter(q_filter).distinct( + fields[0].fields_search[0][0]).order_by( + fields[0].fields_search[0][0]) + else: + qs = qs.order_by(fields[0].fields_search[0][0]) + + qs = qs.values_list( + 'id', fields[0].fields_search[0][0]) + r += list(qs) + + if tipos.count() > 1: + r.sort(key=lambda x: x[1].upper()) + return r + + +class AutoresPossiveisListView(ListAPIView): + """ + Deprecated + + TODO Migrar para customização na api automática + """ + + permission_classes = (IsAuthenticatedOrReadOnly,) + queryset = Autor.objects.all() + model = Autor + + pagination_class = None + + filter_class = AutoresPossiveisFilterSet + serializer_class = AutorChoiceSerializer + + +class MateriaLegislativaViewSet(ListModelMixin, + RetrieveModelMixin, + GenericViewSet): + """ + Deprecated + + TODO Migrar para customização na api automática + """ + + permission_classes = (IsAuthenticated,) + serializer_class = MateriaLegislativaOldSerializer + queryset = MateriaLegislativa.objects.all() + filter_backends = (DjangoFilterBackend,) + filter_fields = ('numero', 'ano', 'tipo', ) + + +class SessaoPlenariaViewSet(ListModelMixin, + RetrieveModelMixin, + GenericViewSet): + """ + Deprecated + + TODO Migrar para customização na api automática + """ + + permission_classes = (AllowAny,) + serializer_class = SessaoPlenariaOldSerializer + queryset = SessaoPlenaria.objects.all() + filter_backends = (DjangoFilterBackend,) + filter_fields = ('data_inicio', 'data_fim', 'interativa') diff --git a/sapl/api/urls.py b/sapl/api/urls.py index e794a4e20..bdcf0e372 100644 --- a/sapl/api/urls.py +++ b/sapl/api/urls.py @@ -5,10 +5,10 @@ from drf_yasg.views import get_schema_view from rest_framework import permissions from rest_framework.routers import DefaultRouter -from sapl.api.views import (AutoresPossiveisListView, AutoresProvaveisListView, - AutorListView, MateriaLegislativaViewSet, - ModelChoiceView, SessaoPlenariaViewSet, - SaplSetViews) +from sapl.api.deprecated import MateriaLegislativaViewSet, SessaoPlenariaViewSet,\ + AutoresProvaveisListView, AutoresPossiveisListView, AutorListView,\ + ModelChoiceView +from sapl.api.views import SaplSetViews from .apps import AppConfig @@ -28,18 +28,6 @@ for app, built_sets in SaplSetViews.items(): urlpatterns_router = router.urls -# TODO: refatorar para customização da api automática -urlpatterns_api = [ - url(r'^autor/provaveis', - AutoresProvaveisListView.as_view(), name='autores_provaveis_list'), - url(r'^autor/possiveis', - AutoresPossiveisListView.as_view(), name='autores_possiveis_list'), - - url(r'^autor', AutorListView.as_view(), name='autor_list'), - - url(r'^model/(?P\d+)/(?P\d*)$', - ModelChoiceView.as_view(), name='model_list'), -] schema_view = get_schema_view( openapi.Info( @@ -52,18 +40,30 @@ schema_view = get_schema_view( permission_classes=(permissions.AllowAny,), ) -urlpatterns_api += [ +urlpatterns_api = [ url(r'^docs/swagger(?P\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'), url(r'^docs/swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'), url(r'^docs/redoc/$', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'), - ] +# TODO: refatorar para customização da api automática +deprecated_urlpatterns_api = [ + url(r'^autor/provaveis', + AutoresProvaveisListView.as_view(), name='autores_provaveis_list'), + url(r'^autor/possiveis', + AutoresPossiveisListView.as_view(), name='autores_possiveis_list'), + + url(r'^autor', AutorListView.as_view(), name='autor_list'), + + url(r'^model/(?P\d+)/(?P\d*)$', + ModelChoiceView.as_view(), name='model_list'), +] urlpatterns = [ + url(r'^api/', include(deprecated_urlpatterns_api)), url(r'^api/', include(urlpatterns_api)), url(r'^api/', include(urlpatterns_router)), diff --git a/sapl/api/views.py b/sapl/api/views.py index 068d2f1c9..dbdcac632 100644 --- a/sapl/api/views.py +++ b/sapl/api/views.py @@ -1,4 +1,3 @@ - import logging from django import apps @@ -6,7 +5,6 @@ from django.conf import settings from django.contrib.contenttypes.models import ContentType from django.db.models import Q from django.db.models.fields.files import FileField -from django.http import Http404 from django.utils.decorators import classonlymethod from django.utils.text import capfirst from django.utils.translation import ugettext_lazy as _ @@ -15,284 +13,13 @@ from django_filters.rest_framework.backends import DjangoFilterBackend from django_filters.rest_framework.filterset import FilterSet from django_filters.utils import resolve_field from rest_framework import serializers as rest_serializers -from rest_framework.decorators import list_route, detail_route,\ - permission_classes -from rest_framework.generics import ListAPIView -from rest_framework.mixins import ListModelMixin, RetrieveModelMixin -from rest_framework.permissions import (IsAuthenticated, - IsAuthenticatedOrReadOnly, AllowAny) -from rest_framework.response import Response -from rest_framework.viewsets import GenericViewSet, ModelViewSet - -from sapl.api.forms import (AutorChoiceFilterSet, AutoresPossiveisFilterSet, - AutorSearchForFieldFilterSet) +from rest_framework.decorators import list_route, detail_route +from rest_framework.viewsets import ModelViewSet + from sapl.api.permissions import SaplModelPermissions -from sapl.api.serializers import (AutorChoiceSerializer, AutorSerializer, - ChoiceSerializer, - ModelChoiceSerializer, - SessaoPlenariaOldSerializer, - MateriaLegislativaOldSerializer) -from sapl.base.models import TipoAutor, Autor from sapl.comissoes.models import Comissao -from sapl.materia.models import MateriaLegislativa, Proposicao +from sapl.materia.models import Proposicao from sapl.parlamentares.models import Parlamentar -from sapl.sessao.models import SessaoPlenaria -from sapl.utils import SaplGenericRelation - - -class ModelChoiceView(ListAPIView): - - # FIXME aplicar permissão correta de usuário - permission_classes = (IsAuthenticated,) - serializer_class = ModelChoiceSerializer - - def get(self, request, *args, **kwargs): - self.model = ContentType.objects.get_for_id( - self.kwargs['content_type']).model_class() - - pagination = request.GET.get('pagination', '') - - if pagination == 'False': - self.pagination_class = None - - return ListAPIView.get(self, request, *args, **kwargs) - - def get_queryset(self): - return self.model.objects.all() - - -class AutorListView(ListAPIView): - """ - Listagem de Autores com filtro para autores já cadastrados - e/ou possíveis autores. - - - tr - tipo do resultado - Prepera Lista de Autores para 3 cenários distintos - - - default = 1 - - = 1 -> para (value, text) usados geralmente - em combobox, radiobox, checkbox, etc com pesquisa básica - de Autores feita pelo django-filter - -> processo usado nas pesquisas, o mais usado. - - - = 3 -> Devolve instancias da classe Autor filtradas pelo - django-filter - - - tipo - chave primária do Tipo de Autor a ser filtrado - - - q - busca textual no nome do Autor ou em fields_search - declarados no field SaplGenericRelation das GenericFks - A busca textual acontece via django-filter com a - variável `tr` igual 1 ou 3. Em caso contrário, - o django-filter é desativado e a busca é feita - no model do ContentType associado ao tipo. - - - q_0 / q_1 - q_0 é opcional e quando usado, 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_parlamentar__icontains, - parlamentar_set__ativo - &q_1=Carvalho,False - /api/autor?tr=1 - &q_0=parlamentar_set__nome_parlamentar__icontains, - parlamentar_set__ativo - &q_1=Carvalho,True - /api/autor?tr=3 - &q_0=parlamentar_set__nome_parlamentar__icontains, - parlamentar_set__ativo - &q_1=Carvalho,False - /api/autor?tr=3 - &q_0=parlamentar_set__nome_parlamentar__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 - """ - logger = logging.getLogger(__name__) - - TR_AUTOR_CHOICE_SERIALIZER = 1 - TR_AUTOR_SERIALIZER = 3 - - permission_classes = (IsAuthenticatedOrReadOnly,) - queryset = Autor.objects.all() - model = Autor - - filter_class = AutorChoiceFilterSet - filter_backends = (DjangoFilterBackend, ) - serializer_class = AutorChoiceSerializer - - @property - def tr(self): - username = self.request.user.username - try: - tr = int(self.request.GET.get - ('tr', AutorListView.TR_AUTOR_CHOICE_SERIALIZER)) - - if tr not in (AutorListView.TR_AUTOR_CHOICE_SERIALIZER, - AutorListView.TR_AUTOR_SERIALIZER): - return AutorListView.TR_AUTOR_CHOICE_SERIALIZER - except Exception as e: - self.logger.error('user=' + username + '. ' + str(e)) - return AutorListView.TR_AUTOR_CHOICE_SERIALIZER - return tr - - def get(self, request, *args, **kwargs): - if self.tr == AutorListView.TR_AUTOR_SERIALIZER: - 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) - - -class AutoresProvaveisListView(ListAPIView): - logger = logging.getLogger(__name__) - - permission_classes = (IsAuthenticatedOrReadOnly,) - queryset = Autor.objects.all() - model = Autor - - filter_class = None - filter_backends = [] - serializer_class = ChoiceSerializer - - def get_queryset(self): - - params = {'content_type__isnull': False} - username = self.request.user.username - tipo = '' - try: - tipo = int(self.request.GET.get('tipo', '')) - if tipo: - params['id'] = tipo - except Exception as e: - self.logger.error('user= ' + username + '. ' + str(e)) - pass - - tipos = TipoAutor.objects.filter(**params) - - if not tipos.exists() and tipo: - raise Http404() - - r = [] - for tipo in tipos: - q = self.request.GET.get('q', '').strip() - - model_class = tipo.content_type.model_class() - - fields = list(filter( - lambda field: isinstance(field, SaplGenericRelation) and - field.related_model == Autor, - model_class._meta.get_fields(include_hidden=True))) - - """ - fields - é um array de SaplGenericRelation que deve possuir o - atributo fields_search. Verifique na documentação da classe - a estrutura de fields_search. - """ - - assert len(fields) >= 1, (_( - 'Não foi encontrado em %(model)s um atributo do tipo ' - 'SaplGenericRelation que use o model %(model_autor)s') % { - 'model': model_class._meta.verbose_name, - 'model_autor': Autor._meta.verbose_name}) - - qs = model_class.objects.all() - - q_filter = Q() - if q: - for item in fields: - if item.related_model != Autor: - continue - q_fs = Q() - for field in item.fields_search: - q_fs = q_fs | Q(**{'%s%s' % ( - field[0], - field[1]): q}) - q_filter = q_filter & q_fs - - qs = qs.filter(q_filter).distinct( - fields[0].fields_search[0][0]).order_by( - fields[0].fields_search[0][0]) - else: - qs = qs.order_by(fields[0].fields_search[0][0]) - - qs = qs.values_list( - 'id', fields[0].fields_search[0][0]) - r += list(qs) - - if tipos.count() > 1: - r.sort(key=lambda x: x[1].upper()) - return r - - -class AutoresPossiveisListView(ListAPIView): - - permission_classes = (IsAuthenticatedOrReadOnly,) - queryset = Autor.objects.all() - model = Autor - - pagination_class = None - - filter_class = AutoresPossiveisFilterSet - serializer_class = AutorChoiceSerializer - - -class MateriaLegislativaViewSet(ListModelMixin, - RetrieveModelMixin, - GenericViewSet): - - permission_classes = (IsAuthenticated,) - serializer_class = MateriaLegislativaOldSerializer - queryset = MateriaLegislativa.objects.all() - filter_backends = (DjangoFilterBackend,) - filter_fields = ('numero', 'ano', 'tipo', ) - - -class SessaoPlenariaViewSet(ListModelMixin, - RetrieveModelMixin, - GenericViewSet): - - permission_classes = (AllowAny,) - serializer_class = SessaoPlenariaOldSerializer - queryset = SessaoPlenaria.objects.all() - filter_backends = (DjangoFilterBackend,) - filter_fields = ('data_inicio', 'data_fim', 'interativa') class SaplApiViewSetConstrutor(ModelViewSet):