mirror of https://github.com/interlegis/sapl.git
Leandro Roberto
6 years ago
3 changed files with 348 additions and 295 deletions
@ -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') |
Loading…
Reference in new issue