Browse Source

ajustes automáticos da IDE no app api

pull/3453/head
Leandro Roberto 3 years ago
parent
commit
ca9ecf00c0
  1. 7
      sapl/api/core/__init__.py
  2. 2
      sapl/api/core/filters.py
  3. 9
      sapl/api/deprecated.py
  4. 10
      sapl/api/forms.py
  5. 18
      sapl/api/serializers.py
  6. 36
      sapl/api/urls.py
  7. 29
      sapl/api/views_customize.py

7
sapl/api/core/__init__.py

@ -22,11 +22,12 @@ from rest_framework.viewsets import ModelViewSet
from sapl.api.core.filters import SaplFilterSetMixin from sapl.api.core.filters import SaplFilterSetMixin
from sapl.api.permissions import SaplModelPermissions from sapl.api.permissions import SaplModelPermissions
from sapl.api.serializers import ChoiceSerializer, ParlamentarSerializer,\ from sapl.api.serializers import ChoiceSerializer, ParlamentarSerializer, \
ParlamentarEditSerializer, ParlamentarResumeSerializer ParlamentarEditSerializer, ParlamentarResumeSerializer
class BusinessRulesNotImplementedMixin: class BusinessRulesNotImplementedMixin:
def create(self, request, *args, **kwargs): def create(self, request, *args, **kwargs):
raise Exception(_("POST Create não implementado")) raise Exception(_("POST Create não implementado"))
@ -126,6 +127,7 @@ class SaplApiViewSetConstrutor():
# 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): class SaplFilterSet(_filterset_class):
class Meta(_meta_filterset): class Meta(_meta_filterset):
if not hasattr(_meta_filterset, 'model'): if not hasattr(_meta_filterset, 'model'):
model = _model model = _model
@ -159,7 +161,6 @@ class SaplApiViewSetConstrutor():
return cls return cls
""" """
1. Constroi uma rest_framework.viewsets.ModelViewSet para 1. Constroi uma rest_framework.viewsets.ModelViewSet para
todos os models de todas as apps do sapl todos os models de todas as apps do sapl
@ -232,6 +233,7 @@ class SaplApiViewSetConstrutor():
class wrapper_queryset_response_for_drf_action(object): class wrapper_queryset_response_for_drf_action(object):
def __init__(self, model): def __init__(self, model):
self.model = model self.model = model
@ -268,6 +270,7 @@ class wrapper_queryset_response_for_drf_action(object):
# decorator para recuperar e transformar o default # decorator para recuperar e transformar o default
class customize(object): class customize(object):
def __init__(self, model): def __init__(self, model):
self.model = model self.model = model

2
sapl/api/core/filters.py

@ -3,11 +3,11 @@ from collections import OrderedDict
from django.db.models.fields.files import FileField from django.db.models.fields.files import FileField
from django.template.defaultfilters import capfirst from django.template.defaultfilters import capfirst
import django_filters
from django_filters.constants import ALL_FIELDS from django_filters.constants import ALL_FIELDS
from django_filters.filters import CharFilter from django_filters.filters import CharFilter
from django_filters.filterset import FilterSet from django_filters.filterset import FilterSet
from django_filters.utils import resolve_field, get_all_model_fields from django_filters.utils import resolve_field, get_all_model_fields
import django_filters
class SaplFilterSetMixin(FilterSet): class SaplFilterSetMixin(FilterSet):

9
sapl/api/deprecated.py

@ -1,5 +1,4 @@
import logging
import logging import logging
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
@ -10,19 +9,17 @@ 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 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.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 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
from rest_framework.permissions import (IsAuthenticated, 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.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
@ -514,7 +511,7 @@ class AutorListView(ListAPIView):
model = Autor model = Autor
filter_class = AutorChoiceFilterSet filter_class = AutorChoiceFilterSet
filter_backends = (DjangoFilterBackend, ) filter_backends = (DjangoFilterBackend,)
serializer_class = AutorChoiceSerializer serializer_class = AutorChoiceSerializer
@property @property
@ -660,7 +657,7 @@ class MateriaLegislativaViewSet(ListModelMixin,
serializer_class = MateriaLegislativaOldSerializer serializer_class = MateriaLegislativaOldSerializer
queryset = MateriaLegislativa.objects.all() queryset = MateriaLegislativa.objects.all()
filter_backends = (DjangoFilterBackend,) filter_backends = (DjangoFilterBackend,)
filter_fields = ('numero', 'ano', 'tipo', ) filter_fields = ('numero', 'ano', 'tipo',)
class SessaoPlenariaViewSet(ListModelMixin, class SessaoPlenariaViewSet(ListModelMixin,

10
sapl/api/forms.py

@ -2,7 +2,17 @@
from sapl.api.core.filters import SaplFilterSetMixin from sapl.api.core.filters import SaplFilterSetMixin
from sapl.sessao.models import SessaoPlenaria from sapl.sessao.models import SessaoPlenaria
# esta classe não é necessária
# a api construiría uma igual
# mas está demonstrar que caso queira customizar um filter_set
# que a api consiga recuperá-lo, para os endpoints básicos
# deve seguir os critérios de nomenclatura e herança
# class [Model]FilterSet(SaplFilterSetMixin):
# class Meta(SaplFilterSetMixin.Meta):
class SessaoPlenariaFilterSet(SaplFilterSetMixin): class SessaoPlenariaFilterSet(SaplFilterSetMixin):
class Meta(SaplFilterSetMixin.Meta): class Meta(SaplFilterSetMixin.Meta):
model = SessaoPlenaria model = SessaoPlenaria

18
sapl/api/serializers.py

@ -1,16 +1,18 @@
import logging import logging
from django.conf import settings from django.conf import settings
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from django.db.models import F, Q from django.db.models import Q
from image_cropping.utils import get_backend
from rest_framework import serializers from rest_framework import serializers
from rest_framework.relations import StringRelatedField from rest_framework.relations import StringRelatedField
from sapl.parlamentares.models import Parlamentar, Mandato, Filiacao, Legislatura
from sapl.base.models import Autor, CasaLegislativa from sapl.base.models import Autor, CasaLegislativa
from sapl.utils import filiacao_data from sapl.parlamentares.models import Parlamentar, Mandato, Legislatura
from image_cropping.utils import get_backend
class IntRelatedField(StringRelatedField): class IntRelatedField(StringRelatedField):
def to_representation(self, value): def to_representation(self, value):
return int(value) return int(value)
@ -86,7 +88,7 @@ class ParlamentarResumeSerializer(serializers.ModelSerializer):
fotografia_cropped = serializers.SerializerMethodField('crop_fotografia') fotografia_cropped = serializers.SerializerMethodField('crop_fotografia')
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def crop_fotografia(self,obj): def crop_fotografia(self, obj):
thumbnail_url = "" thumbnail_url = ""
try: try:
import os import os
@ -107,7 +109,7 @@ class ParlamentarResumeSerializer(serializers.ModelSerializer):
return thumbnail_url return thumbnail_url
def check_titular(self,obj): def check_titular(self, obj):
is_titular = None is_titular = None
if not Legislatura.objects.exists(): if not Legislatura.objects.exists():
self.logger.error("Não há legislaturas cadastradas.") self.logger.error("Não há legislaturas cadastradas.")
@ -128,14 +130,14 @@ class ParlamentarResumeSerializer(serializers.ModelSerializer):
is_titular = '-' is_titular = '-'
return is_titular return is_titular
def check_partido(self,obj): def check_partido(self, obj):
# Coloca a filiação atual ao invés da última # Coloca a filiação atual ao invés da última
# As condições para mostrar a filiação são: # As condições para mostrar a filiação são:
# A data de filiacao deve ser menor que a data de fim # A data de filiacao deve ser menor que a data de fim
# da legislatura e data de desfiliação deve nula, ou maior, # da legislatura e data de desfiliação deve nula, ou maior,
# ou igual a data de fim da legislatura # ou igual a data de fim da legislatura
username = self.context['request'].user.username username = self.context['request'].user.username
if not Legislatura.objects.exists(): if not Legislatura.objects.exists():
self.logger.error("Não há legislaturas cadastradas.") self.logger.error("Não há legislaturas cadastradas.")
return "" return ""

36
sapl/api/urls.py

@ -1,32 +1,28 @@
from django.conf.urls import include, url from django.conf.urls import include, url
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView,\ from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView, \
SpectacularRedocView SpectacularRedocView
from rest_framework.routers import DefaultRouter from rest_framework.routers import DefaultRouter
from sapl.api.deprecated import MateriaLegislativaViewSet, SessaoPlenariaViewSet,\ from sapl.api.deprecated import MateriaLegislativaViewSet, SessaoPlenariaViewSet, \
AutoresProvaveisListView, AutoresPossiveisListView, AutorListView,\ AutoresProvaveisListView, AutoresPossiveisListView, AutorListView, \
ModelChoiceView ModelChoiceView
from sapl.api.views import AppVersionView, recria_token from sapl.api.views import AppVersionView, recria_token
from sapl.api.views_customize import SaplApiViewSetConstrutor from sapl.api.views_customize import SaplApiViewSetConstrutor
from .apps import AppConfig from .apps import AppConfig
app_name = AppConfig.name app_name = AppConfig.name
router = DefaultRouter() router = DefaultRouter()
router.register(r'materia$', MateriaLegislativaViewSet) router.register(r'materia$', MateriaLegislativaViewSet)
router.register(r'sessao-plenaria', SessaoPlenariaViewSet) router.register(r'sessao-plenaria', SessaoPlenariaViewSet)
for app, built_sets in SaplApiViewSetConstrutor._built_sets.items(): for app, built_sets in SaplApiViewSetConstrutor._built_sets.items():
for view_prefix, viewset in built_sets.items(): for view_prefix, viewset in built_sets.items():
router.register(app.label + '/' + router.register(app.label + '/' +
view_prefix._meta.model_name, viewset) view_prefix._meta.model_name, viewset)
urlpatterns_router = router.urls urlpatterns_router = router.urls
urlpatterns_api_doc = [ urlpatterns_api_doc = [
@ -38,28 +34,6 @@ urlpatterns_api_doc = [
# YOUR PATTERNS # YOUR PATTERNS
url('^schema/', SpectacularAPIView.as_view(), name='schema_api'), url('^schema/', SpectacularAPIView.as_view(), name='schema_api'),
] ]
"""if 'drf_yasg' in settings.INSTALLED_APPS:
from drf_yasg import openapi
from drf_yasg.views import get_schema_view
schema_view = get_schema_view(
openapi.Info(
title="Sapl API - docs",
default_version='v1',
description="Sapl API - Docs - Configuração Básica",
),
url=settings.SITE_URL,
public=True,
permission_classes=(permissions.AllowAny,),
)
urlpatterns_api_doc = [
url(r'^docs/swagger(?P<format>\.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 # TODO: refatorar para customização da api automática
deprecated_urlpatterns_api = [ deprecated_urlpatterns_api = [
@ -67,13 +41,9 @@ deprecated_urlpatterns_api = [
AutoresProvaveisListView.as_view(), name='autores_provaveis_list'), AutoresProvaveisListView.as_view(), name='autores_provaveis_list'),
url(r'^autor/possiveis', url(r'^autor/possiveis',
AutoresPossiveisListView.as_view(), name='autores_possiveis_list'), AutoresPossiveisListView.as_view(), name='autores_possiveis_list'),
url(r'^autor', AutorListView.as_view(), name='autor_list'), url(r'^autor', AutorListView.as_view(), name='autor_list'),
url(r'^model/(?P<content_type>\d+)/(?P<pk>\d*)$', url(r'^model/(?P<content_type>\d+)/(?P<pk>\d*)$',
ModelChoiceView.as_view(), name='model_list'), ModelChoiceView.as_view(), name='model_list'),
] ]
urlpatterns = [ urlpatterns = [

29
sapl/api/views_customize.py

@ -8,24 +8,23 @@ from django.utils.translation import ugettext_lazy as _
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from sapl.api.core import customize, SaplApiViewSetConstrutor,\ from sapl.api.core import customize, SaplApiViewSetConstrutor, \
wrapper_queryset_response_for_drf_action,\ wrapper_queryset_response_for_drf_action, \
BusinessRulesNotImplementedMixin BusinessRulesNotImplementedMixin
from sapl.api.permissions import SaplModelPermissions from sapl.api.permissions import SaplModelPermissions
from sapl.api.serializers import ChoiceSerializer, \ from sapl.api.serializers import ChoiceSerializer, \
ParlamentarEditSerializer, ParlamentarResumeSerializer ParlamentarEditSerializer, ParlamentarResumeSerializer
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, TipoMateriaLegislativa,\ from sapl.materia.models import Proposicao, TipoMateriaLegislativa, \
MateriaLegislativa, Tramitacao MateriaLegislativa, Tramitacao
from sapl.norma.models import NormaJuridica from sapl.norma.models import NormaJuridica
from sapl.parlamentares.models import Mandato, Legislatura from sapl.parlamentares.models import Mandato, Legislatura
from sapl.parlamentares.models import Parlamentar from sapl.parlamentares.models import Parlamentar
from sapl.protocoloadm.models import DocumentoAdministrativo,\ from sapl.protocoloadm.models import DocumentoAdministrativo, \
DocumentoAcessorioAdministrativo, TramitacaoAdministrativo, Anexado DocumentoAcessorioAdministrativo, TramitacaoAdministrativo, Anexado
from sapl.sessao.models import SessaoPlenaria, ExpedienteSessao from sapl.sessao.models import SessaoPlenaria, ExpedienteSessao
from sapl.utils import models_with_gr_for_model, choice_anos_com_sessaoplenaria from sapl.utils import models_with_gr_for_model, choice_anos_com_sessaoplenaria
SaplApiViewSetConstrutor = SaplApiViewSetConstrutor.build_class() SaplApiViewSetConstrutor = SaplApiViewSetConstrutor.build_class()
@ -33,7 +32,7 @@ SaplApiViewSetConstrutor = SaplApiViewSetConstrutor.build_class()
class _AutorViewSet: class _AutorViewSet:
# Customização para AutorViewSet com implementação de actions específicas # Customização para AutorViewSet com implementação de actions específicas
""" """
Neste exemplo de customização do que foi criado em Nesta customização do que foi criado em
SaplApiViewSetConstrutor além do ofertado por SaplApiViewSetConstrutor além do ofertado por
rest_framework.viewsets.ModelViewSet, dentre outras customizações rest_framework.viewsets.ModelViewSet, dentre outras customizações
possíveis, foi adicionado as rotas referentes aos relacionamentos genéricos possíveis, foi adicionado as rotas referentes aos relacionamentos genéricos
@ -100,7 +99,9 @@ class _AutorViewSet:
@customize(Parlamentar) @customize(Parlamentar)
class _ParlamentarViewSet: class _ParlamentarViewSet:
class ParlamentarPermission(SaplModelPermissions): class ParlamentarPermission(SaplModelPermissions):
def has_permission(self, request, view): def has_permission(self, request, view):
if request.method == 'GET': if request.method == 'GET':
return True return True
@ -108,7 +109,7 @@ class _ParlamentarViewSet:
perm = super().has_permission(request, view) perm = super().has_permission(request, view)
return perm return perm
permission_classes = (ParlamentarPermission, ) permission_classes = (ParlamentarPermission,)
def get_serializer(self, *args, **kwargs): def get_serializer(self, *args, **kwargs):
if self.request.user.has_perm('parlamentares.add_parlamentar'): if self.request.user.has_perm('parlamentares.add_parlamentar'):
@ -219,7 +220,9 @@ class _ProposicaoViewSet:
* Pode recuperar qualquer das proposições incorporadas * Pode recuperar qualquer das proposições incorporadas
""" """
class ProposicaoPermission(SaplModelPermissions): class ProposicaoPermission(SaplModelPermissions):
def has_permission(self, request, view): def has_permission(self, request, view):
if request.method == 'GET': if request.method == 'GET':
return True return True
@ -234,7 +237,7 @@ class _ProposicaoViewSet:
# não é list ou detail, então passa pelas regras de permissão e, # não é list ou detail, então passa pelas regras de permissão e,
# depois disso ainda passa pelo filtro de get_queryset # depois disso ainda passa pelo filtro de get_queryset
permission_classes = (ProposicaoPermission, ) permission_classes = (ProposicaoPermission,)
def get_queryset(self): def get_queryset(self):
qs = super().get_queryset() qs = super().get_queryset()
@ -259,6 +262,7 @@ class _ProposicaoViewSet:
@customize(MateriaLegislativa) @customize(MateriaLegislativa)
class _MateriaLegislativaViewSet: class _MateriaLegislativaViewSet:
class Meta: class Meta:
ordering = ['-ano', 'tipo', 'numero'] ordering = ['-ano', 'tipo', 'numero']
@ -305,6 +309,7 @@ class _TipoMateriaLegislativaViewSet:
class _DocumentoAdministrativoViewSet: class _DocumentoAdministrativoViewSet:
class DocumentoAdministrativoPermission(SaplModelPermissions): class DocumentoAdministrativoPermission(SaplModelPermissions):
def has_permission(self, request, view): def has_permission(self, request, view):
if request.method == 'GET': if request.method == 'GET':
comportamento = AppConfig.attr('documentos_administrativos') comportamento = AppConfig.attr('documentos_administrativos')
@ -320,7 +325,7 @@ class _DocumentoAdministrativoViewSet:
""" """
return super().has_permission(request, view) return super().has_permission(request, view)
permission_classes = (DocumentoAdministrativoPermission, ) permission_classes = (DocumentoAdministrativoPermission,)
def get_queryset(self): def get_queryset(self):
""" """
@ -340,7 +345,7 @@ class _DocumentoAdministrativoViewSet:
class _DocumentoAcessorioAdministrativoViewSet: class _DocumentoAcessorioAdministrativoViewSet:
permission_classes = ( permission_classes = (
_DocumentoAdministrativoViewSet.DocumentoAdministrativoPermission, ) _DocumentoAdministrativoViewSet.DocumentoAdministrativoPermission,)
def get_queryset(self): def get_queryset(self):
qs = super().get_queryset() qs = super().get_queryset()
@ -355,7 +360,7 @@ class _TramitacaoAdministrativoViewSet(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 = (
_DocumentoAdministrativoViewSet.DocumentoAdministrativoPermission, ) _DocumentoAdministrativoViewSet.DocumentoAdministrativoPermission,)
def get_queryset(self): def get_queryset(self):
qs = super().get_queryset() qs = super().get_queryset()
@ -369,7 +374,7 @@ class _TramitacaoAdministrativoViewSet(BusinessRulesNotImplementedMixin):
class _AnexadoViewSet(BusinessRulesNotImplementedMixin): class _AnexadoViewSet(BusinessRulesNotImplementedMixin):
permission_classes = ( permission_classes = (
_DocumentoAdministrativoViewSet.DocumentoAdministrativoPermission, ) _DocumentoAdministrativoViewSet.DocumentoAdministrativoPermission,)
def get_queryset(self): def get_queryset(self):
qs = super().get_queryset() qs = super().get_queryset()

Loading…
Cancel
Save