diff --git a/sapl/materia/migrations/0088_fix_view_materiaemtramitacao.py b/sapl/materia/migrations/0088_fix_view_materiaemtramitacao.py new file mode 100644 index 000000000..1f3ca52d8 --- /dev/null +++ b/sapl/materia/migrations/0088_fix_view_materiaemtramitacao.py @@ -0,0 +1,62 @@ +from django.db import migrations, models + +_OLD_VIEW = """ + create or replace view materia_materiaemtramitacao as + select m.id as id, + m.id as materia_id, + t.id as tramitacao_id, + t.unidade_tramitacao_destino_id as unidade_tramitacao_atual_id + from materia_materialegislativa m + inner join materia_tramitacao t on (m.id = t.materia_id) + where t.id = (select max(id) from materia_tramitacao where materia_id = m.id) + order by m.id DESC +""" + +_NEW_VIEW = """ + create or replace view materia_materiaemtramitacao as + select distinct on (m.id) + m.id as id, + m.id as materia_id, + t.id as tramitacao_id, + t.unidade_tramitacao_destino_id as unidade_tramitacao_atual_id + from materia_materialegislativa m + inner join materia_tramitacao t on t.materia_id = m.id + order by m.id desc, t.id desc +""" + + +class Migration(migrations.Migration): + # CREATE INDEX CONCURRENTLY cannot run inside a transaction. + atomic = False + + dependencies = [ + ('materia', '0087_update_viewdb_materiaemtramitacao'), + ] + + operations = [ + migrations.RunSQL(sql=_NEW_VIEW, reverse_sql=_OLD_VIEW), + migrations.SeparateDatabaseAndState( + database_operations=[ + migrations.RunSQL( + sql=""" + CREATE INDEX CONCURRENTLY IF NOT EXISTS + tram_materia_id_desc + ON materia_tramitacao (materia_id, id DESC) + """, + reverse_sql=""" + DROP INDEX CONCURRENTLY IF EXISTS + tram_materia_id_desc + """, + ), + ], + state_operations=[ + migrations.AddIndex( + model_name='tramitacao', + index=models.Index( + fields=['materia', '-id'], + name='tram_materia_id_desc', + ), + ), + ], + ), + ] diff --git a/sapl/materia/models.py b/sapl/materia/models.py index bdeb402e3..fb0df6ee5 100644 --- a/sapl/materia/models.py +++ b/sapl/materia/models.py @@ -1350,6 +1350,9 @@ class Tramitacao(models.Model): verbose_name = _('Tramitação') verbose_name_plural = _('Tramitações') ordering = ('-data_tramitacao', '-id') + indexes = [ + models.Index(fields=['materia', '-id'], name='tram_materia_id_desc'), + ] def __str__(self): return _('%(materia)s | %(status)s | %(data)s') % { diff --git a/sapl/relatorios/forms.py b/sapl/relatorios/forms.py index 23145f899..58868a061 100644 --- a/sapl/relatorios/forms.py +++ b/sapl/relatorios/forms.py @@ -543,9 +543,7 @@ class RelatorioMateriasTramitacaoFilterSet(django_filters.FilterSet): @property def qs(self): parent = super(RelatorioMateriasTramitacaoFilterSet, self).qs - return parent.distinct().order_by( - '-materia__ano', 'materia__tipo', '-materia__numero' - ) + return parent.order_by('-materia__ano', 'materia__tipo', '-materia__numero') class Meta: model = MateriaEmTramitacao diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py index 73c1494f2..25cd9ea21 100755 --- a/sapl/relatorios/views.py +++ b/sapl/relatorios/views.py @@ -51,8 +51,7 @@ from sapl.sessao.views import (get_identificacao_basica, get_mesa_diretora, from sapl.settings import MEDIA_URL from sapl.settings import STATIC_ROOT from sapl.utils import LISTA_DE_UFS, TrocaTag, filiacao_data, create_barcode, show_results_filter_set, \ - num_materias_por_tipo, parlamentares_ativos, MultiFormatOutputMixin -from sapl.middleware.ratelimit import smart_key, smart_rate + num_materias_por_tipo, parlamentares_ativos, MultiFormatOutputMixin, is_report_allowed from .templates import (pdf_capa_processo_gerar, pdf_documento_administrativo_gerar, pdf_espelho_gerar, pdf_etiqueta_protocolo_gerar, pdf_materia_gerar, @@ -60,8 +59,6 @@ from .templates import (pdf_capa_processo_gerar, pdf_protocolo_gerar, pdf_sessao_plenaria_gerar) from sapl.crud.base import make_pagination -from ratelimit.decorators import ratelimit -from django.utils.decorators import method_decorator def get_kwargs_params(request, fields): @@ -1850,26 +1847,18 @@ class RelatoriosListView(TemplateView): class RelatorioMixin: # TODO: verificar se todos os relatorios de sistema/relatorios extendem esse Mixin def get(self, request, *args, **kwargs): - super(RelatorioMixin, self).get(request) - - # TODO: import as global - from sapl.utils import is_report_allowed if not is_report_allowed(request): raise Http404() - is_relatorio = request.GET.get('relatorio') - context = self.get_context_data(filter=self.filterset) - - if is_relatorio: + if request.GET.get('relatorio'): + filterset_class = self.get_filterset_class() + self.filterset = self.get_filterset(filterset_class) + context = self.get_context_data(filter=self.filterset) return self.relatorio(request, context) - else: - return self.render_to_response(context) + + return super(RelatorioMixin, self).get(request, *args, **kwargs) -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioDocumentosAcessoriosView(RelatorioMixin, FilterView): model = DocumentoAcessorio filterset_class = RelatorioDocumentosAcessoriosFilterSet @@ -1914,10 +1903,6 @@ class RelatorioDocumentosAcessoriosView(RelatorioMixin, FilterView): return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioVotacoesNominaisView(RelatorioMixin, MultiFormatOutputMixin, FilterView): model = VotoParlamentar filterset_class = RelatorioVotacoesNominaisFilterSet @@ -1987,10 +1972,6 @@ class RelatorioVotacoesNominaisView(RelatorioMixin, MultiFormatOutputMixin, Filt return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioAtasView(RelatorioMixin, FilterView): model = SessaoPlenaria filterset_class = RelatorioAtasFilterSet @@ -2016,10 +1997,6 @@ class RelatorioAtasView(RelatorioMixin, FilterView): return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioPresencaSessaoView(RelatorioMixin, FilterView): logger = logging.getLogger(__name__) model = SessaoPlenaria @@ -2254,10 +2231,6 @@ class RelatorioPresencaSessaoView(RelatorioMixin, FilterView): return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioHistoricoTramitacaoView(RelatorioMixin, FilterView): model = MateriaLegislativa filterset_class = RelatorioHistoricoTramitacaoFilterSet @@ -2315,10 +2288,6 @@ class RelatorioHistoricoTramitacaoView(RelatorioMixin, FilterView): return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioDataFimPrazoTramitacaoView(RelatorioMixin, FilterView): model = MateriaEmTramitacao filterset_class = RelatorioDataFimPrazoTramitacaoFilterSet @@ -2382,10 +2351,6 @@ class RelatorioDataFimPrazoTramitacaoView(RelatorioMixin, FilterView): return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioReuniaoView(RelatorioMixin, FilterView): model = Reuniao filterset_class = RelatorioReuniaoFilterSet @@ -2420,10 +2385,6 @@ class RelatorioReuniaoView(RelatorioMixin, FilterView): return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioAudienciaView(RelatorioMixin, FilterView): model = AudienciaPublica filterset_class = RelatorioAudienciaFilterSet @@ -2458,10 +2419,6 @@ class RelatorioAudienciaView(RelatorioMixin, FilterView): return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioMateriasTramitacaoView(RelatorioMixin, FilterView): model = MateriaEmTramitacao filterset_class = RelatorioMateriasTramitacaoFilterSet @@ -2576,10 +2533,6 @@ class RelatorioMateriasTramitacaoView(RelatorioMixin, FilterView): return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioMateriasPorAnoAutorTipoView(RelatorioMixin, FilterView): model = MateriaLegislativa filterset_class = RelatorioMateriasPorAnoAutorTipoFilterSet @@ -2659,10 +2612,6 @@ class RelatorioMateriasPorAnoAutorTipoView(RelatorioMixin, FilterView): return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioMateriasPorAutorView(RelatorioMixin, FilterView): model = MateriaLegislativa filterset_class = RelatorioMateriasPorAutorFilterSet @@ -2734,10 +2683,6 @@ class RelatorioMateriaAnoAssuntoView(ListView): return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioNormasPublicadasMesView(RelatorioMixin, FilterView): model = NormaJuridica filterset_class = RelatorioNormasMesFilterSet @@ -2778,10 +2723,6 @@ class RelatorioNormasPublicadasMesView(RelatorioMixin, FilterView): return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioNormasVigenciaView(RelatorioMixin, FilterView): model = NormaJuridica filterset_class = RelatorioNormasVigenciaFilterSet @@ -2846,10 +2787,6 @@ class RelatorioNormasVigenciaView(RelatorioMixin, FilterView): return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioHistoricoTramitacaoAdmView(RelatorioMixin, FilterView): model = DocumentoAdministrativo filterset_class = RelatorioHistoricoTramitacaoAdmFilterSet @@ -2900,10 +2837,6 @@ class RelatorioHistoricoTramitacaoAdmView(RelatorioMixin, FilterView): return context -@method_decorator(ratelimit(key=smart_key, - rate=smart_rate, - block=True), - name='dispatch') class RelatorioNormasPorAutorView(RelatorioMixin, FilterView): model = NormaJuridica filterset_class = RelatorioNormasPorAutorFilterSet diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py index 35c24eb18..5ca38cab1 100755 --- a/sapl/sessao/views.py +++ b/sapl/sessao/views.py @@ -9,7 +9,7 @@ from django.contrib import messages from django.contrib.auth.decorators import permission_required from django.contrib.auth.mixins import PermissionRequiredMixin from django.core.exceptions import ObjectDoesNotExist -from django.db.models import Max, Q +from django.db.models import Max, Prefetch, Q from django.http import JsonResponse from django.http.response import Http404, HttpResponseRedirect from django.urls import reverse @@ -174,7 +174,7 @@ def verifica_sessao_iniciada(request, spk, is_leitura=False): aux_text = 'leitura' if is_leitura else 'votação' logger.info('user=' + username + '. Não é possível abrir matérias para {}. ' 'Esta SessaoPlenaria (id={}) não foi iniciada ou está finalizada.'.format( - aux_text, spk)) + aux_text, spk)) msg = _('Não é possível abrir matérias para {}. ' 'Esta Sessão Plenária não foi iniciada ou está finalizada.' ' Vá em "Abertura"->"Dados Básicos" e altere os valores dos campos necessários.'.format(aux_text)) @@ -226,38 +226,43 @@ def abrir_votacao(request, pk, spk): def customize_link_materia(context, pk, has_permission, is_expediente): + # sessao_plenaria is the same for every row — resolve once + object_list = context['object_list'] + if object_list: + sessao_plenaria = object_list[0].sessao_plenaria + else: + sessao_plenaria = SessaoPlenaria.objects.get(id=pk) + data_sessao = sessao_plenaria.data_fim or sessao_plenaria.data_inicio + for i, row in enumerate(context['rows']): - materia = context['object_list'][i].materia - obj = context['object_list'][i] + obj = object_list[i] + materia = obj.materia # already select_related + url_materia = reverse( 'sapl.materia:materialegislativa_detail', kwargs={'pk': materia.id}) - numeracao = materia.numeracao_set.first() if materia.numeracao_set.first() else "-" - todos_autoria = materia.autoria_set.all() - autoria = todos_autoria.filter(primeiro_autor=True) + + numeracao = materia._numeracao_prefetch[0] if materia._numeracao_prefetch else "-" + + todos_autoria = materia._autoria_prefetch + autoria = [a for a in todos_autoria if a.primeiro_autor] autor = ', '.join([str(a.autor) for a in autoria]) if autoria else "-" + todos_autores = ', '.join([str(a.autor) for a in todos_autoria]) if autoria else "-" - todos_autores = ', '.join([str(a.autor) - for a in todos_autoria]) if autoria else "-" + num_protocolo = materia.numero_protocolo or "-" - num_protocolo = materia.numero_protocolo if materia.numero_protocolo else "-" - sessao_plenaria = SessaoPlenaria.objects.get(id=pk) - data_sessao = sessao_plenaria.data_fim if sessao_plenaria.data_fim else sessao_plenaria.data_inicio - tramitacao = Tramitacao.objects \ - .select_related('materia', 'status', 'materia__tipo') \ - .filter(materia=materia, turno__isnull=False, data_tramitacao__lte=data_sessao) \ - .exclude(turno__exact='') \ - .order_by('-data_tramitacao', '-id') \ - .first() + tramitacao = next( + (t for t in materia._tramitacao_prefetch if t.data_tramitacao <= data_sessao), + None, + ) turno = '-' if tramitacao: for t in Tramitacao.TURNO_CHOICES: if t[0] == tramitacao.turno: turno = t[1] break - materia_em_tramitacao = MateriaEmTramitacao.objects \ - .select_related("materia", "tramitacao") \ - .filter(materia=materia) \ - .first() + + materia_em_tramitacao = materia._met_prefetch[0] if materia._met_prefetch else None + # idUnica para cada materia idAutor = "autor" + str(i) idAutores = "autores" + str(i) @@ -283,12 +288,9 @@ def customize_link_materia(context, pk, has_permission, is_expediente): # url em toda a string de title_materia context['rows'][i][1] = (title_materia, None) - exist_resultado = obj.registrovotacao_set.filter( - materia=obj.materia).exists() - exist_retirada = obj.retiradapauta_set.filter( - materia=obj.materia).exists() - exist_leitura = obj.registroleitura_set.filter( - materia=obj.materia).exists() + exist_resultado = bool(obj._votacao_prefetch) + exist_retirada = bool(obj._retirada_prefetch) + exist_leitura = bool(obj._leitura_prefetch) if (obj.tipo_votacao != LEITURA and not exist_resultado and not exist_retirada) or \ (obj.tipo_votacao == LEITURA and not exist_leitura): @@ -410,8 +412,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente): resultado = '''Não há resultado''' elif exist_retirada: - retirada = obj.retiradapauta_set.filter( - materia_id=obj.materia_id).last() + retirada = obj._retirada_prefetch[-1] retirada_descricao = retirada.tipo_de_retirada.descricao retirada_observacao = retirada.observacao url = reverse('sapl.sessao:retiradapauta_detail', @@ -423,13 +424,11 @@ def customize_link_materia(context, pk, has_permission, is_expediente): else: if obj.tipo_votacao == LEITURA: - resultado = obj.registroleitura_set.filter( - materia_id=obj.materia_id).last() + resultado = obj._leitura_prefetch[-1] resultado_descricao = "Matéria lida" resultado_observacao = resultado.observacao else: - resultado = obj.registrovotacao_set.filter( - materia_id=obj.materia_id).last() + resultado = obj._votacao_prefetch[-1] resultado_descricao = resultado.tipo_resultado_votacao.nome resultado_observacao = resultado.observacao @@ -488,11 +487,11 @@ def customize_link_materia(context, pk, has_permission, is_expediente): 'mid': obj.materia_id}) resultado = ( - '%s

%s
' % ( - url, - context.get('page', 1), - resultado_descricao, - resultado_observacao)) + '%s

%s
' % ( + url, + context.get('page', 1), + resultado_descricao, + resultado_observacao)) else: if obj.tipo_votacao == NOMINAL: @@ -503,7 +502,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente): 'pk': obj.sessao_plenaria_id, 'oid': obj.pk, 'mid': obj.materia_id}) + \ - '?&materia=expediente' + '?&materia=expediente' else: url = reverse( 'sapl.sessao:votacao_nominal_transparencia', @@ -511,7 +510,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente): 'pk': obj.sessao_plenaria_id, 'oid': obj.pk, 'mid': obj.materia_id}) + \ - '?&materia=ordem' + '?&materia=ordem' resultado = ('%s
%s
' % (url, @@ -526,7 +525,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente): 'pk': obj.sessao_plenaria_id, 'oid': obj.pk, 'mid': obj.materia_id}) + \ - '?&materia=expediente' + '?&materia=expediente' else: url = reverse( 'sapl.sessao:votacao_simbolica_transparencia', @@ -534,7 +533,7 @@ def customize_link_materia(context, pk, has_permission, is_expediente): 'pk': obj.sessao_plenaria_id, 'oid': obj.pk, 'mid': obj.materia_id}) + \ - '?&materia=ordem' + '?&materia=ordem' resultado = ('%s
%s
' % (url, @@ -798,7 +797,7 @@ class MateriaOrdemDiaCrud(MasterDetailCrud): sessao_plenaria=self.kwargs['pk']).aggregate( Max('numero_ordem'))['numero_ordem__max'] self.initial['numero_ordem'] = ( - max_numero_ordem if max_numero_ordem else 0) + 1 + max_numero_ordem if max_numero_ordem else 0) + 1 return self.initial def get_success_url(self): @@ -835,20 +834,58 @@ class MateriaOrdemDiaCrud(MasterDetailCrud): layout_key = 'OrdemDiaDetail' class ListView(MasterDetailCrud.ListView): - paginate_by = None + paginate_by = 100 ordering = ['numero_ordem', 'materia', 'resultado'] def get_context_data(self, **kwargs): - if self.get_queryset().count() > 500: - self.paginate_by = 50 - else: - self.paginate_by = None - context = super().get_context_data(**kwargs) - has_permition = self.request.user.has_module_perms(AppConfig.label) return customize_link_materia(context, self.kwargs['pk'], has_permition, False) + def get_queryset(self): + return super().get_queryset().select_related( + 'materia', 'materia__tipo', 'sessao_plenaria', + ).prefetch_related( + Prefetch( + 'materia__materiaemtramitacao_set', + to_attr='_met_prefetch', + ), + Prefetch( + 'materia__numeracao_set', + to_attr='_numeracao_prefetch', + ), + Prefetch( + 'materia__autoria_set', + queryset=Autoria.objects.select_related('autor'), + to_attr='_autoria_prefetch', + ), + Prefetch( + 'materia__tramitacao_set', + queryset=Tramitacao.objects.filter( + turno__isnull=False, + ).exclude(turno='').order_by('-data_tramitacao', '-id'), + to_attr='_tramitacao_prefetch', + ), + Prefetch( + 'registrovotacao_set', + queryset=RegistroVotacao.objects.select_related( + 'tipo_resultado_votacao', + ), + to_attr='_votacao_prefetch', + ), + Prefetch( + 'retiradapauta_set', + queryset=RetiradaPauta.objects.select_related( + 'tipo_de_retirada', + ), + to_attr='_retirada_prefetch', + ), + Prefetch( + 'registroleitura_set', + to_attr='_leitura_prefetch', + ), + ) + def recuperar_materia(request): tipo = TipoMateriaLegislativa.objects.get(pk=request.GET['tipo_materia']) @@ -907,24 +944,60 @@ class ExpedienteMateriaCrud(MasterDetailCrud): 'resultado'] class ListView(MasterDetailCrud.ListView): - paginate_by = None + paginate_by = 100 ordering = ['numero_ordem', 'materia', 'resultado'] def get_context_data(self, **kwargs): - - if self.get_queryset().count() > 500: - self.paginate_by = 50 - else: - self.paginate_by = None - context = super().get_context_data(**kwargs) - if self.request.GET.get('page'): context['page'] = self.request.GET.get('page') - has_permition = self.request.user.has_module_perms(AppConfig.label) return customize_link_materia(context, self.kwargs['pk'], has_permition, True) + def get_queryset(self): + return super().get_queryset().select_related( + 'materia', 'materia__tipo', 'sessao_plenaria', + ).prefetch_related( + Prefetch( + 'materia__materiaemtramitacao_set', + to_attr='_met_prefetch', + ), + Prefetch( + 'materia__numeracao_set', + to_attr='_numeracao_prefetch', + ), + Prefetch( + 'materia__autoria_set', + queryset=Autoria.objects.select_related('autor'), + to_attr='_autoria_prefetch', + ), + Prefetch( + 'materia__tramitacao_set', + queryset=Tramitacao.objects.filter( + turno__isnull=False, + ).exclude(turno='').order_by('-data_tramitacao', '-id'), + to_attr='_tramitacao_prefetch', + ), + Prefetch( + 'registrovotacao_set', + queryset=RegistroVotacao.objects.select_related( + 'tipo_resultado_votacao', + ), + to_attr='_votacao_prefetch', + ), + Prefetch( + 'retiradapauta_set', + queryset=RetiradaPauta.objects.select_related( + 'tipo_de_retirada', + ), + to_attr='_retirada_prefetch', + ), + Prefetch( + 'registroleitura_set', + to_attr='_leitura_prefetch', + ), + ) + class CreateView(MasterDetailCrud.CreateView): form_class = ExpedienteMateriaForm @@ -941,7 +1014,7 @@ class ExpedienteMateriaCrud(MasterDetailCrud): sessao_plenaria=self.kwargs['pk']).aggregate( Max('numero_ordem'))['numero_ordem__max'] initial['numero_ordem'] = ( - max_numero_ordem if max_numero_ordem else 0) + 1 + max_numero_ordem if max_numero_ordem else 0) + 1 return initial def get_success_url(self): @@ -975,7 +1048,6 @@ class ExpedienteMateriaCrud(MasterDetailCrud): return initial class DetailView(MasterDetailCrud.DetailView): - layout_key = 'ExpedienteMateriaDetail' @@ -1426,7 +1498,7 @@ class PresencaView(FormMixin, PresencaMixin, DetailView): # Id dos parlamentares presentes marcados = request.POST.getlist('presenca_ativos') \ - + request.POST.getlist('presenca_inativos') + + request.POST.getlist('presenca_inativos') # Deletar os que foram desmarcados deletar = set(presentes_banco) - set(marcados) @@ -1541,7 +1613,7 @@ class PresencaOrdemDiaView(FormMixin, PresencaMixin, DetailView): # Id dos parlamentares presentes marcados = request.POST.getlist('presenca_ativos') \ - + request.POST.getlist('presenca_inativos') + + request.POST.getlist('presenca_inativos') # Deletar os que foram desmarcados deletar = set(presentes_banco) - set(marcados) @@ -1803,7 +1875,7 @@ def insere_parlamentar_composicao(request): username = request.user.username if request.user.has_perm( '%s.add_%s' % ( - AppConfig.label, IntegranteMesa._meta.model_name)): + AppConfig.label, IntegranteMesa._meta.model_name)): composicao = IntegranteMesa() @@ -1867,7 +1939,7 @@ def remove_parlamentar_composicao(request): username = request.user.username if request.POST and request.user.has_perm( '%s.delete_%s' % ( - AppConfig.label, IntegranteMesa._meta.model_name)): + AppConfig.label, IntegranteMesa._meta.model_name)): if 'composicao_mesa' in request.POST: try: @@ -2921,7 +2993,7 @@ class VotacaoView(SessaoPermissionMixin): username = request.user.username self.logger.error('user=' + username + '. Problemas ao salvar RegistroVotacao da materia de id={} ' 'e da ordem de id={}. '.format(materia_id, ordem_id) + str( - e)) + e)) return self.form_invalid(form) else: ordem = OrdemDia.objects.get(id=ordem_id) @@ -3991,7 +4063,8 @@ class PautaSessaoDetailView(PautaMultiFormatOutputMixin, DetailView): 'resultado_observacao': resultado_observacao, 'situacao': ultima_tramitacao.status if ultima_tramitacao else _("Não informada"), 'processo': f'{str(numeracao.numero_materia)}/{str(numeracao.ano_materia)}' if numeracao else '-', - 'autor': [str(x.autor) for x in Autoria.objects.select_related("autor").filter(materia_id=o.materia_id)], + 'autor': [str(x.autor) for x in + Autoria.objects.select_related("autor").filter(materia_id=o.materia_id)], 'turno': get_turno(ultima_tramitacao.turno) if ultima_tramitacao else '', 'periodo': 'ordem dia', }) @@ -4099,7 +4172,6 @@ class PesquisarSessaoPlenariaView(MultiFormatOutputMixin, FilterView): return r - class PesquisarPautaSessaoView(PesquisarSessaoPlenariaView): filterset_class = PautaSessaoFilterSet template_name = 'sessao/pauta_sessao_filter.html' @@ -5338,7 +5410,7 @@ class CorrespondenciaCrud(MasterDetailCrud): sessao_plenaria=self.kwargs['pk']).aggregate( Max('numero_ordem'))['numero_ordem__max'] initial['numero_ordem'] = ( - max_numero_ordem if max_numero_ordem else 0) + 1 + max_numero_ordem if max_numero_ordem else 0) + 1 return initial diff --git a/sapl/utils.py b/sapl/utils.py index 191ea87a0..0c0220a3d 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -1,6 +1,6 @@ import csv import string -from functools import wraps +from functools import lru_cache, wraps import hashlib import io from itertools import groupby, chain @@ -959,13 +959,15 @@ def parlamentares_ativos(data_inicio, data_fim=None): return Parlamentar.objects.filter(id__in=parlamentares_id) -def show_results_filter_set(qr): - query_params = set(qr.keys()) - if ((len(query_params) == 1 and 'iframe' in query_params) or - len(query_params) == 0): - return False +_IGNORED_PARAMS = frozenset({'iframe', 'pesquisar', 'csrfmiddlewaretoken'}) - return True + +def show_results_filter_set(qr): + meaningful = { + k for k, v in qr.items() + if k not in _IGNORED_PARAMS and v and v.strip() + } + return bool(meaningful) def sort_lista_chave(lista, chave): @@ -1249,7 +1251,7 @@ class GoogleRecapthaMixin: return cd -# TODO: cache this map and invalidate on each update +@lru_cache(maxsize=None) def get_report_urls_map(): from django.urls import get_resolver from django.urls.base import reverse @@ -1278,13 +1280,11 @@ def get_report_urls_map(): def is_report_allowed(request, url_path=None): - from sapl.utils import get_report_urls_map # TODO: import global - url_map = get_report_urls_map() # TODO: cache this!!! Globally - + url_map = get_report_urls_map() path = url_path if url_path else request.path - authenticated = True if request.user.is_authenticated else False + authenticated = request.user.is_authenticated - if path in url_map.keys(): + if path in url_map: path_metadata = url_map[path] if not authenticated and path_metadata['public']: return True