Repository: interlegis/sapl

Issue:
Refatorar pesquisa de normas para django-filters



Discussion:

Resolving patch:
diff --git a/sapl/norma/forms.py b/sapl/norma/forms.py
--- a/sapl/norma/forms.py
+++ b/sapl/norma/forms.py
@@ -1,16 +1,18 @@
 from datetime import datetime
 
+import django_filters
 from crispy_forms.helper import FormHelper
 from crispy_forms.layout import Fieldset, Layout
 from django import forms
 from django.core.exceptions import ObjectDoesNotExist, ValidationError
+from django.db import models
 from django.forms import ModelForm, widgets
 from django.utils.translation import ugettext_lazy as _
 
 from sapl.crispy_layout_mixin import form_actions, to_row
 from sapl.materia.models import MateriaLegislativa, TipoMateriaLegislativa
 from sapl.settings import MAX_DOC_UPLOAD_SIZE
-from sapl.utils import RANGE_ANOS
+from sapl.utils import RANGE_ANOS, RangeWidgetOverride
 
 from .models import AssuntoNorma, NormaJuridica
 
@@ -30,94 +32,43 @@ def get_esferas():
                      ('data,tipo,ano,numero', _('Data/Tipo/Ano/Número'))]
 
 
-# TODO termos, pesquisa textual, assunto(M2M)
-class NormaJuridicaPesquisaForm(ModelForm):
-
-    periodo_inicial = forms.DateField(label=u'Período Inicial',
-                                      input_formats=['%d/%m/%Y'],
-                                      required=False,
-                                      widget=forms.DateInput(
-                                          format='%d/%m/%Y',
-                                          attrs={'class': 'dateinput'}))
-
-    periodo_final = forms.DateField(label=u'Período Final',
-                                    input_formats=['%d/%m/%Y'],
-                                    required=False,
-                                    widget=forms.DateInput(
-                                        format='%d/%m/%Y',
-                                        attrs={'class': 'dateinput'}))
-
-    publicacao_inicial = forms.DateField(label=u'Publicação Inicial',
-                                         input_formats=['%d/%m/%Y'],
-                                         required=False,
-                                         widget=forms.DateInput(
-                                             format='%d/%m/%Y',
-                                             attrs={'class': 'dateinput'}))
-
-    publicacao_final = forms.DateField(label=u'Publicação Final',
-                                       input_formats=['%d/%m/%Y'],
-                                       required=False,
-                                       widget=forms.DateInput(
-                                           format='%d/%m/%Y',
-                                           attrs={'class': 'dateinput'}))
-
-    ano = forms.ModelChoiceField(
-        label='Ano',
-        required=False,
-        queryset=NormaJuridica.objects.order_by('-ano').values_list(
-            'ano', flat=True).distinct(),
-        empty_label='Selecione'
-    )
+class NormaFilterSet(django_filters.FilterSet):
 
-    em_vigencia = forms.ChoiceField(
-        label='Em vigência?',
-        choices=YES_NO_CHOICES,
-        required=False)
+    RANGE_ANOS.insert(0, ('', 'Selecione'))
 
-    ordenacao = forms.ChoiceField(
-        label='Ordenação',
-        choices=ORDENACAO_CHOICES,
-        required=False)
+    filter_overrides = {models.DateField: {
+        'filter_class': django_filters.DateFromToRangeFilter,
+        'extra': lambda f: {
+            'label': '%s (%s)' % (f.verbose_name, _('Inicial - Final')),
+            'widget': RangeWidgetOverride}
+    }}
 
-    numero = forms.IntegerField(required=False)
+    ano = django_filters.ChoiceFilter(required=False,
+                                      label=u'Ano',
+                                      choices=RANGE_ANOS)
 
-    assunto = forms.ModelChoiceField(
-        label='Assunto',
-        required=False,
-        queryset=AssuntoNorma.objects.all(),
-        empty_label='Selecione'
-    )
+    ementa = django_filters.CharFilter(lookup_expr='icontains')
 
     class Meta:
         model = NormaJuridica
-        fields = ['tipo',
-                  'numero',
-                  'ano',
-                  'periodo_inicial',
-                  'periodo_final',
-                  'publicacao_inicial',
-                  'publicacao_final',
-                  'assunto']
+        fields = ['tipo', 'numero', 'ano', 'data',
+                  'data_publicacao', 'ementa', 'assuntos']
 
     def __init__(self, *args, **kwargs):
-
-        row1 = to_row([('tipo', 12)])
-
-        row2 = to_row([('numero', 6), ('ano', 6)])
-
-        row3 = to_row([('periodo_inicial', 6), ('periodo_final', 6)])
-
-        row4 = to_row([('publicacao_inicial', 6), ('publicacao_final', 6)])
-
-        row5 = to_row([('em_vigencia', 4), ('ordenacao', 4), ('assunto', 4)])
-
-        self.helper = FormHelper()
-        self.helper.layout = Layout(
-            Fieldset('Pesquisa Norma Juridica',
-                     row1, row2, row3, row4, row5),
-            form_actions(save_label='Pesquisar')
+        super(NormaFilterSet, self).__init__(*args, **kwargs)
+
+        row1 = to_row([('tipo', 4), ('numero', 4), ('ano', 4)])
+        row2 = to_row([('data', 6), ('data_publicacao', 6)])
+        row3 = to_row([('ementa', 12)])
+        row4 = to_row([('assuntos', 12)])
+
+        self.form.helper = FormHelper()
+        self.form.helper.form_method = 'GET'
+        self.form.helper.layout = Layout(
+            Fieldset(_('Pesquisa de Norma'),
+                     row1, row2, row3, row4,
+                     form_actions(save_label='Pesquisar'))
         )
-        super(NormaJuridicaPesquisaForm, self).__init__(*args, **kwargs)
 
 
 class NormaJuridicaForm(ModelForm):
diff --git a/sapl/norma/urls.py b/sapl/norma/urls.py
--- a/sapl/norma/urls.py
+++ b/sapl/norma/urls.py
@@ -1,8 +1,7 @@
 from django.conf.urls import include, url
 
-from sapl.norma.views import (AssuntoNormaCrud,
-                              NormaCrud, NormaPesquisaView, NormaTaView,
-                              PesquisaNormaListView, TipoNormaCrud)
+from sapl.norma.views import (AssuntoNormaCrud, NormaCrud, NormaPesquisaView,
+                              TipoNormaCrud, NormaTaView)
 
 from .apps import AppConfig
 
@@ -17,8 +16,7 @@
 
     url(r'^sistema/norma/tipo/', include(TipoNormaCrud.get_urls())),
     url(r'^sistema/norma/assunto/', include(AssuntoNormaCrud.get_urls())),
-    url(r'^norma/pesquisa$',
+
+    url(r'^norma/pesquisar$',
         NormaPesquisaView.as_view(), name='norma_pesquisa'),
-    url(r'^norma/pesquisa-resultado$',
-        PesquisaNormaListView.as_view(), name='list_pesquisa_norma'),
 ]
diff --git a/sapl/norma/views.py b/sapl/norma/views.py
--- a/sapl/norma/views.py
+++ b/sapl/norma/views.py
@@ -2,18 +2,18 @@
 
 from django.core.urlresolvers import reverse
 from django.shortcuts import redirect
+from django.utils.translation import ugettext_lazy as _
 from django.views.generic import FormView, ListView
 from django.views.generic.base import RedirectView
+from django_filters.views import FilterView
 
 from sapl.base.models import AppConfig
 from sapl.compilacao.views import IntegracaoTaView
 from sapl.crud.base import (RP_DETAIL, RP_LIST, Crud, CrudAux,
                             MasterDetailCrud, make_pagination)
-from sapl.norma.forms import NormaJuridicaForm
 
-from .forms import NormaJuridicaPesquisaForm
-from .models import (AssuntoNorma, NormaJuridica,
-                     TipoNormaJuridica)
+from .forms import NormaFilterSet, NormaJuridicaForm
+from .models import AssuntoNorma, NormaJuridica, TipoNormaJuridica
 
 # LegislacaoCitadaCrud = Crud.build(LegislacaoCitada, '')
 AssuntoNormaCrud = CrudAux.build(AssuntoNorma, 'assunto_norma_juridica',
@@ -25,6 +25,32 @@
     list_field_names=['sigla', 'descricao', 'equivalente_lexml'])
 
 
+class NormaPesquisaView(FilterView):
+    model = NormaJuridica
+    filterset_class = NormaFilterSet
+    paginate_by = 10
+
+    def get_context_data(self, **kwargs):
+        context = super(NormaPesquisaView, self).get_context_data(**kwargs)
+
+        context['title'] = _('Pesquisar Norma Jurídica')
+
+        qr = self.request.GET.copy()
+
+        if 'page' in qr:
+            del qr['page']
+
+        paginator = context['paginator']
+        page_obj = context['page_obj']
+
+        context['page_range'] = make_pagination(
+            page_obj.number, paginator.num_pages)
+
+        context['filter_url'] = ('&' + qr.urlencode()) if len(qr) > 0 else ''
+
+        return context
+
+
 class NormaTaView(IntegracaoTaView):
     model = NormaJuridica
     model_type_foreignkey = TipoNormaJuridica
@@ -103,113 +129,3 @@ def get_initial(self):
                 self.initial['ano_materia'] = norma.materia.ano
                 self.initial['numero_materia'] = norma.materia.numero
             return self.initial.copy()
-
-
-class NormaPesquisaView(FormView):
-    template_name = "norma/pesquisa.html"
-    success_url = "norma:norma_pesquisa"
-    form_class = NormaJuridicaPesquisaForm
-
-    def post(self, request, *args, **kwargs):
-        form = NormaJuridicaPesquisaForm(request.POST)
-
-        if form.data['tipo']:
-            kwargs['tipo'] = form.data['tipo']
-        if form.data['numero']:
-            kwargs['numero'] = form.data['numero']
-        if form.data['ano']:
-            kwargs['ano'] = form.data['ano']
-        if form.data['periodo_inicial'] and form.data['periodo_final']:
-            kwargs['periodo_inicial'] = form.data['periodo_inicial']
-            kwargs['periodo_final'] = form.data['periodo_final']
-        if form.data['publicacao_inicial'] and form.data['publicacao_final']:
-            kwargs['publicacao_inicial'] = form.data['publicacao_inicial']
-            kwargs['publicacao_final'] = form.data['publicacao_final']
-        if form.data['ordenacao']:
-            kwargs['ordenacao'] = form.data['ordenacao']
-        if form.data['em_vigencia']:
-            kwargs['em_vigencia'] = form.data['em_vigencia']
-        if form.data['assunto']:
-            kwargs['assunto'] = form.data['assunto']
-
-        request.session['kwargs'] = kwargs
-        return redirect('sapl.norma:list_pesquisa_norma')
-
-
-class PesquisaNormaListView(ListView):
-    template_name = 'norma/list_pesquisa.html'
-    model = NormaJuridica
-    paginate_by = 10
-
-    def get_queryset(self):
-        kwargs = self.request.session['kwargs']
-
-        if 'ordenacao' in kwargs:
-            ordenacao = kwargs.pop('ordenacao').split(',')
-            for o in ordenacao:
-                normas = NormaJuridica.objects.all().order_by(o)
-        else:
-            normas = NormaJuridica.objects.all()
-
-        if 'em_vigencia' in kwargs:
-            del kwargs['em_vigencia']
-            normas = normas.filter(
-                data_vigencia__lte=datetime.now().date())
-
-        if 'periodo_inicial' and 'publicacao_inicial' in kwargs:
-            periodo_inicial = datetime.strptime(
-                kwargs['periodo_inicial'],
-                '%d/%m/%Y').strftime('%Y-%m-%d')
-            periodo_final = datetime.strptime(
-                kwargs['periodo_final'],
-                '%d/%m/%Y').strftime('%Y-%m-%d')
-            publicacao_inicial = datetime.strptime(
-                kwargs['publicacao_inicial'],
-                '%d/%m/%Y').strftime('%Y-%m-%d')
-            publicacao_final = datetime.strptime(
-                kwargs['publicacao_final'],
-                '%d/%m/%Y').strftime('%Y-%m-%d')
-
-            normas = normas.filter(
-                data__range=(periodo_inicial, periodo_final),
-                data_publicacao__range=(publicacao_inicial, publicacao_final))
-
-        if 'periodo_inicial' in kwargs:
-            inicial = datetime.strptime(kwargs['periodo_inicial'],
-                                        '%d/%m/%Y').strftime('%Y-%m-%d')
-            final = datetime.strptime(kwargs['periodo_inicial'],
-                                      '%d/%m/%Y').strftime('%Y-%m-%d')
-
-            normas = normas.filter(data__range=(inicial, final))
-
-        if 'publicacao_inicial' in kwargs:
-            inicial = datetime.strptime(kwargs['publicacao_inicial'],
-                                        '%d/%m/%Y').strftime('%Y-%m-%d')
-            final = datetime.strptime(kwargs['publicacao_final'],
-                                      '%d/%m/%Y').strftime('%Y-%m-%d')
-
-            normas = normas.filter(data_publicacao__range=(inicial, final))
-        if 'tipo' in kwargs:
-            normas = normas.filter(tipo=kwargs['tipo'])
-
-        if 'numero' in kwargs:
-            normas = normas.filter(numero=kwargs['numero'])
-
-        if 'ano' in kwargs:
-            normas = normas.filter(ano=kwargs['ano'])
-
-        if 'assunto' in kwargs:
-            normas = normas.filter(assuntos=kwargs['assunto'])
-
-        return normas
-
-    def get_context_data(self, **kwargs):
-        context = super(PesquisaNormaListView, self).get_context_data(
-            **kwargs)
-
-        paginator = context['paginator']
-        page_obj = context['page_obj']
-
-        context['page_range'] = make_pagination(
-            page_obj.number, paginator.num_pages)
-        return context


Test patch: