From deee281954fae13049f40656bbebfc812dd7a8d2 Mon Sep 17 00:00:00 2001 From: Edward Oliveira Date: Tue, 23 Jun 2026 17:35:17 -0300 Subject: [PATCH 1/3] Fix ValueError in audiencia form and AttributeError on HEAD requests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - audiencia/forms.py: also catch ValueError when querying MateriaLegislativa by numero, so a non-numeric input (e.g. '36 e 61') surfaces as a form validation error instead of an unhandled 500. - utils.py: MultiFormatOutputMixin.render_to_response was doing getattr(request, request.method) which fails for HEAD requests because Django exposes request.GET/POST but not request.HEAD; remap HEAD → GET. Co-Authored-By: Claude Sonnet 4.6 --- sapl/audiencia/forms.py | 2 +- sapl/utils.py | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sapl/audiencia/forms.py b/sapl/audiencia/forms.py index 211db9855..f1978032f 100755 --- a/sapl/audiencia/forms.py +++ b/sapl/audiencia/forms.py @@ -115,7 +115,7 @@ class AudienciaForm(FileFieldCheckMixin, forms.ModelForm): numero=materia, ano=ano_materia, tipo=tipo_materia) - except ObjectDoesNotExist: + except (ObjectDoesNotExist, ValueError): msg = _('A matéria %s nº %s/%s não existe no cadastro' ' de matérias legislativas.' % (tipo_materia, materia, ano_materia)) self.logger.warning( diff --git a/sapl/utils.py b/sapl/utils.py index ee97094aa..42d4b2c6e 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -1395,8 +1395,9 @@ class MultiFormatOutputMixin: return {fmt: fields for fmt in self.formats_impl} def render_to_response(self, context, **response_kwargs): - format_result = getattr(self.request, self.request.method).get( - 'format', None) + # HEAD shares query params with GET; Django has no request.HEAD attribute. + _method = 'GET' if self.request.method == 'HEAD' else self.request.method + format_result = getattr(self.request, _method).get('format', None) if format_result: if format_result not in self.formats_impl: From 3b5e3747b7d7b5223e03f2fde2fa0fb2bdb91d10 Mon Sep 17 00:00:00 2001 From: Edward Oliveira Date: Fri, 10 Jul 2026 23:28:27 -0300 Subject: [PATCH 2/3] =?UTF-8?q?Fix=20duplicate=20normas/mat=C3=A9rias=20in?= =?UTF-8?q?=20author=20reports=20and=20prevent=20unfiltered=20queries?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RelatorioNormasPorAutorFilterSet: chaining .filter(autorianorma__primeiro_autor=True) after the filterset's own autorianorma__autor filter created a second JOIN, causing each norma to appear once per Autoria with primeiro_autor=True. Removing that filter leaves a single JOIN so DISTINCT works correctly. Both filtersets now return none() when no author is selected, preventing a full-table scan with an unguarded ORDER BY on a related field. Both views pass the Autor object (not str) into context so the templates can compare autoria.autor != autor by PK. Both templates now show only co-authors (those different from the filtered author) in the Coautor(es) column, mirroring each other. RelatorioMateriasPorAutorView: removed the OrderedDict.fromkeys() deduplication workaround that was masking the same underlying JOIN issue. Co-Authored-By: Claude Sonnet 4.6 --- sapl/relatorios/forms.py | 6 +++++- sapl/relatorios/views.py | 9 ++++----- .../RelatorioMateriasPorAutor_filter.html | 14 ++++++-------- .../relatorios/RelatorioNormasPorAutor_filter.html | 8 +++----- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/sapl/relatorios/forms.py b/sapl/relatorios/forms.py index 23145f899..f659c254c 100644 --- a/sapl/relatorios/forms.py +++ b/sapl/relatorios/forms.py @@ -633,6 +633,8 @@ class RelatorioMateriasPorAutorFilterSet(django_filters.FilterSet): @property def qs(self): parent = super().qs + if not self.data.get('autoria__autor'): + return parent.none() return parent.distinct().order_by('-ano', '-numero', 'tipo', 'autoria__autor', '-autoria__primeiro_autor') class Meta(FilterOverridesMetaMixin): @@ -744,7 +746,9 @@ class RelatorioNormasPorAutorFilterSet(django_filters.FilterSet): @property def qs(self): parent = super().qs - return parent.distinct().filter(autorianorma__primeiro_autor=True) \ + if not self.data.get('autorianorma__autor'): + return parent.none() + return parent.distinct() \ .order_by('autorianorma__autor', '-autorianorma__primeiro_autor', 'tipo', '-ano', '-numero') class Meta(FilterOverridesMetaMixin): diff --git a/sapl/relatorios/views.py b/sapl/relatorios/views.py index bc28b3ffc..60ba1635e 100755 --- a/sapl/relatorios/views.py +++ b/sapl/relatorios/views.py @@ -2660,7 +2660,6 @@ class RelatorioMateriasPorAutorView(RelatorioMixin, FilterView): return context qs = context['object_list'] - context['materias_resultado'] = list(collections.OrderedDict.fromkeys(qs)) context['qtdes'] = num_materias_por_tipo(qs) qr = self.request.GET.copy() @@ -2675,9 +2674,9 @@ class RelatorioMateriasPorAutorView(RelatorioMixin, FilterView): context['tipo'] = '' if self.request.GET['autoria__autor']: autor = int(self.request.GET['autoria__autor']) - context['autor'] = (str(Autor.objects.get(id=autor))) + context['autor'] = Autor.objects.get(id=autor) else: - context['autor'] = '' + context['autor'] = None context['periodo'] = ( self.request.GET['data_apresentacao_0'] + ' - ' + self.request.GET['data_apresentacao_1']) @@ -2921,9 +2920,9 @@ class RelatorioNormasPorAutorView(RelatorioMixin, FilterView): if self.request.GET['autorianorma__autor']: autor = int(self.request.GET['autorianorma__autor']) - context['autor'] = (str(Autor.objects.get(id=autor))) + context['autor'] = Autor.objects.get(id=autor) else: - context['autor'] = '' + context['autor'] = None context['periodo'] = ( self.request.GET['data_0'] + ' - ' + self.request.GET['data_1']) diff --git a/sapl/templates/relatorios/RelatorioMateriasPorAutor_filter.html b/sapl/templates/relatorios/RelatorioMateriasPorAutor_filter.html index 5acb303c1..dcd7287e0 100644 --- a/sapl/templates/relatorios/RelatorioMateriasPorAutor_filter.html +++ b/sapl/templates/relatorios/RelatorioMateriasPorAutor_filter.html @@ -17,7 +17,7 @@  Tipo de matéria: {{ tipo }}
 Data de apresentação: {{ periodo }}


- {% if materias_resultado %} + {% if object_list %} @@ -43,10 +43,10 @@ - + - {% for materia in materias_resultado %} + {% for materia in object_list %} diff --git a/sapl/templates/relatorios/RelatorioNormasPorAutor_filter.html b/sapl/templates/relatorios/RelatorioNormasPorAutor_filter.html index c3f045301..51c987c34 100644 --- a/sapl/templates/relatorios/RelatorioNormasPorAutor_filter.html +++ b/sapl/templates/relatorios/RelatorioNormasPorAutor_filter.html @@ -54,13 +54,11 @@ From 0caaf4d402b23c17ba142dd3a57278d386b1c740 Mon Sep 17 00:00:00 2001 From: Edward Oliveira Date: Sat, 11 Jul 2026 15:01:52 -0300 Subject: [PATCH 3/3] =?UTF-8?q?hot-fix:=20imprime=20somente=20cont=C3=A9ud?= =?UTF-8?q?o=20da=20ocorr=C3=AAncia?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blocos_sessao_plenaria/ocorrencias_da_sessao.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/templates/relatorios/blocos_sessao_plenaria/ocorrencias_da_sessao.html b/sapl/templates/relatorios/blocos_sessao_plenaria/ocorrencias_da_sessao.html index f37c899be..fc2016b83 100644 --- a/sapl/templates/relatorios/blocos_sessao_plenaria/ocorrencias_da_sessao.html +++ b/sapl/templates/relatorios/blocos_sessao_plenaria/ocorrencias_da_sessao.html @@ -1,4 +1,4 @@

Ocorrências da Sessão

{% for o in lst_ocorrencias%} -

{{o|striptags|safe}}

+

{{o.conteudo|striptags|safe}}

{% endfor %}
Matéria EmentaAutor(es)Coautor(es)
@@ -56,11 +56,9 @@ {% autoescape off %}{{materia.ementa}}
{{materia.observacao}}{% endautoescape %}
- {% for autor in materia.autoria_set.all %} - {% if not autor.primeiro_autor %} - {{ autor.autor }}
- {% else %} - {{ autor.autor }}
+ {% for autoria in materia.autoria_set.all %} + {% if autoria.autor != autor %} + {{ autoria.autor }}
{% endif %} {% endfor %}
{% autoescape off %}{{norma.ementa}}
{{norma.observacao}}{% endautoescape %}
- {% if norma.autorianorma_set.first != norma.autorianorma_set.last %} - {% for autor in norma.autorianorma_set.all %} - {% if not autor.primeiro_autor %} - {{ autor.autor }}
+ {% for autoria in norma.autorianorma_set.all %} + {% if autoria.autor != autor %} + {{ autoria.autor }}
{% endif %} {% endfor %} - {% endif %}