Browse Source

adiciona Textos Articulados na pesquisa textual

pull/1594/head
LeandroRoberto 8 years ago
parent
commit
529c312aa4
  1. 131
      sapl/base/search_indexes.py
  2. 16
      sapl/compilacao/views.py
  3. 5
      sapl/materia/views.py
  4. 6
      sapl/templates/search/search.html

131
sapl/base/search_indexes.py

@ -3,33 +3,36 @@ import os.path
import re import re
import string import string
import textract from django.db.models import Q, F, Value
from django.db.models.fields import TextField
from django.db.models.fields.files import FieldFile
from django.db.models.functions import Concat
from django.template import loader from django.template import loader
from haystack import indexes from haystack.constants import Indexable
from haystack.fields import CharField
from haystack.indexes import SearchIndex
from haystack.utils import get_model_ct_tuple
from textract.exceptions import ExtensionNotSupported from textract.exceptions import ExtensionNotSupported
import textract
from sapl.compilacao.models import TextoArticulado, Dispositivo,\
STATUS_TA_PUBLIC, STATUS_TA_IMMUTABLE_PUBLIC
from sapl.materia.models import DocumentoAcessorio, MateriaLegislativa from sapl.materia.models import DocumentoAcessorio, MateriaLegislativa
from sapl.norma.models import NormaJuridica from sapl.norma.models import NormaJuridica
from sapl.settings import BASE_DIR, SOLR_URL from sapl.settings import BASE_DIR, SOLR_URL
logger = logging.getLogger(BASE_DIR.name)
class DocumentoAcessorioIndex(indexes.SearchIndex, indexes.Indexable): logger = logging.getLogger(BASE_DIR.name)
text = indexes.CharField(document=True, use_template=True)
filename = 'arquivo'
model = DocumentoAcessorio
template_name = 'materia/documentoacessorio_text.txt'
def get_model(self): class TextExtractField(CharField):
return self.model
def index_queryset(self, using=None): def __init__(self, **kwargs):
return self.get_model().objects.all() super().__init__(**kwargs)
assert self.model_attr
def get_updated_field(self): if not isinstance(self.model_attr, (list, tuple)):
return 'data_ultima_atualizacao' self.model_attr = (self.model_attr, )
def solr_extraction(self, arquivo): def solr_extraction(self, arquivo):
extracted_data = self._get_backend(None).extract_file_contents( extracted_data = self._get_backend(None).extract_file_contents(
@ -59,71 +62,99 @@ class DocumentoAcessorioIndex(indexes.SearchIndex, indexes.Indexable):
print(msg) print(msg)
logger.error(msg) logger.error(msg)
def prepare(self, obj): def extract_data(self, obj):
if not self.filename or not self.model or not self.template_name:
data = []
for attr in self.model_attr:
if not hasattr(obj, attr):
raise Exception raise Exception
data = super(DocumentoAcessorioIndex, self).prepare(obj) value = getattr(obj, attr)
arquivo = getattr(obj, self.filename) if not value:
continue
if arquivo: if isinstance(value, FieldFile):
if not os.path.exists(arquivo.path): if not os.path.exists(value.path):
return self.prepared_data continue
if not os.path.splitext(arquivo.path)[1][:1]: if not os.path.splitext(value.path)[1][:1]:
return self.prepared_data continue
# Em ambiente de produção utiliza-se o SOLR # Em ambiente de produção utiliza-se o SOLR
if SOLR_URL: if SOLR_URL:
try: try:
extracted_data = self.solr_extraction(arquivo) data.append(self.solr_extraction(value))
except Exception: except Exception:
self.print_error(arquivo) self.print_error(value)
return self.prepared_data
# Em ambiente de DEV utiliza-se o Whoosh # Em ambiente de DEV utiliza-se o Whoosh
# Como ele não possui extração, faz-se uso do textract # Como ele não possui extração, faz-se uso do textract
else: else:
try: try:
extracted_data = self.whoosh_extraction(arquivo) data.append(self.whoosh_extraction(value))
except ExtensionNotSupported as e: except ExtensionNotSupported as e:
print(str(e)) print(str(e))
logger.error(str(e)) logger.error(str(e))
return self.prepared_data
except Exception: except Exception:
self.print_error(arquivo) self.print_error(value)
return self.prepared_data
# Now we'll finally perform the template processing to render the elif hasattr(value, 'model') and value.model == TextoArticulado:
# text field with *all* of our metadata visible for templating:
t = loader.select_template((
'search/indexes/' + self.template_name, ))
data['text'] = t.render({'object': obj,
'extracted': extracted_data})
return data for ta in value.filter(privacidade__in=[
STATUS_TA_PUBLIC,
STATUS_TA_IMMUTABLE_PUBLIC]):
dispositivos = Dispositivo.objects.filter(
Q(ta=ta) | Q(ta_publicado=ta)
).order_by(
'ordem'
).annotate(
rotulo_texto=Concat(
F('rotulo'), Value(' '), F('texto'),
output_field=TextField(),
)
).values_list(
'rotulo_texto', flat=True)
data += list(filter(lambda x: x.strip(), dispositivos))
return self.prepared_data return ' '.join(data)
def prepare_template(self, obj):
app_label, model_name = get_model_ct_tuple(obj)
template_names = ['search/indexes/%s/%s_%s.txt' %
(app_label, model_name, self.instance_name)]
class MateriaLegislativaIndex(DocumentoAcessorioIndex): t = loader.select_template(template_names)
text = indexes.CharField(document=True, use_template=True)
filename = 'texto_original' return t.render({'object': obj,
model = MateriaLegislativa 'extracted': self.extract_data(obj)})
template_name = 'materia/materialegislativa_text.txt'
class DocumentoAcessorioIndex(SearchIndex, Indexable):
model = DocumentoAcessorio
text = TextExtractField(
document=True, use_template=True, model_attr='arquivo')
def get_model(self):
return self.model
def index_queryset(self, using=None):
return self.get_model().objects.all()
def get_updated_field(self): def get_updated_field(self):
return 'data_ultima_atualizacao' return 'data_ultima_atualizacao'
class NormaJuridicaIndex(DocumentoAcessorioIndex): class NormaJuridicaIndex(DocumentoAcessorioIndex):
text = indexes.CharField(document=True, use_template=True)
filename = 'texto_integral'
model = NormaJuridica model = NormaJuridica
template_name = 'norma/normajuridica_text.txt' text = TextExtractField(
model_attr=('texto_integral', 'texto_articulado'),
document=True, use_template=True, )
def get_updated_field(self):
return 'data_ultima_atualizacao' class MateriaLegislativaIndex(DocumentoAcessorioIndex):
model = MateriaLegislativa
text = TextExtractField(
model_attr=('texto_original', 'texto_articulado'),
document=True, use_template=True, )

16
sapl/compilacao/views.py

@ -1,7 +1,7 @@
import logging
import sys
from collections import OrderedDict from collections import OrderedDict
from datetime import timedelta from datetime import timedelta
import logging
import sys
from braces.views import FormMessagesMixin from braces.views import FormMessagesMixin
from django import forms from django import forms
@ -19,8 +19,8 @@ from django.http.response import (HttpResponse, HttpResponseRedirect,
from django.shortcuts import get_object_or_404, redirect from django.shortcuts import get_object_or_404, redirect
from django.utils.dateparse import parse_date from django.utils.dateparse import parse_date
from django.utils.encoding import force_text from django.utils.encoding import force_text
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import string_concat from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy as _
from django.views.generic.base import TemplateView from django.views.generic.base import TemplateView
from django.views.generic.detail import DetailView from django.views.generic.detail import DetailView
from django.views.generic.edit import (CreateView, DeleteView, FormView, from django.views.generic.edit import (CreateView, DeleteView, FormView,
@ -50,6 +50,7 @@ from sapl.compilacao.utils import (DISPOSITIVO_SELECT_RELATED,
from sapl.crud.base import Crud, CrudListView, make_pagination from sapl.crud.base import Crud, CrudListView, make_pagination
from sapl.settings import BASE_DIR from sapl.settings import BASE_DIR
TipoNotaCrud = Crud.build(TipoNota, 'tipo_nota') TipoNotaCrud = Crud.build(TipoNota, 'tipo_nota')
TipoVideCrud = Crud.build(TipoVide, 'tipo_vide') TipoVideCrud = Crud.build(TipoVide, 'tipo_vide')
TipoPublicacaoCrud = Crud.build(TipoPublicacao, 'tipo_publicacao') TipoPublicacaoCrud = Crud.build(TipoPublicacao, 'tipo_publicacao')
@ -1157,10 +1158,14 @@ class TextEditView(CompMixin, TemplateView):
self.object.save() self.object.save()
messages.success(request, _( messages.success(request, _(
'Texto Articulado desbloqueado com sucesso.')) 'Texto Articulado desbloqueado com sucesso.'))
if self.object.content_object:
self.object.content_object.save()
else: else:
if 'lock' in request.GET: if 'lock' in request.GET:
# TODO - implementar logging de ação de usuário
# TODO - implementar logging de ação de usuário
notificacoes = self.get_notificacoes( notificacoes = self.get_notificacoes(
object_list=self.object.dispositivos_set.all(), object_list=self.object.dispositivos_set.all(),
type_notificacoes=['danger', ]) type_notificacoes=['danger', ])
@ -1183,6 +1188,9 @@ class TextEditView(CompMixin, TemplateView):
messages.success(request, _( messages.success(request, _(
'Texto Articulado bloqueado com sucesso.')) 'Texto Articulado bloqueado com sucesso.'))
if self.object.content_object:
self.object.content_object.save()
return redirect(to=reverse_lazy( return redirect(to=reverse_lazy(
'sapl.compilacao:ta_text', kwargs={ 'sapl.compilacao:ta_text', kwargs={
'ta_id': self.object.id})) 'ta_id': self.object.id}))

5
sapl/materia/views.py

@ -2,7 +2,6 @@ from datetime import datetime
from random import choice from random import choice
from string import ascii_letters, digits from string import ascii_letters, digits
import weasyprint
from crispy_forms.helper import FormHelper from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML from crispy_forms.layout import HTML
from django.contrib import messages from django.contrib import messages
@ -20,8 +19,8 @@ from django.views.generic import CreateView, ListView, TemplateView, UpdateView
from django.views.generic.base import RedirectView from django.views.generic.base import RedirectView
from django.views.generic.edit import FormView from django.views.generic.edit import FormView
from django_filters.views import FilterView from django_filters.views import FilterView
import weasyprint
import sapl
from sapl.base.models import Autor, CasaLegislativa from sapl.base.models import Autor, CasaLegislativa
from sapl.comissoes.models import Comissao, Participacao from sapl.comissoes.models import Comissao, Participacao
from sapl.compilacao.models import (STATUS_TA_IMMUTABLE_RESTRICT, from sapl.compilacao.models import (STATUS_TA_IMMUTABLE_RESTRICT,
@ -42,6 +41,7 @@ from sapl.protocoloadm.models import Protocolo
from sapl.utils import (TURNO_TRAMITACAO_CHOICES, YES_NO_CHOICES, autor_label, from sapl.utils import (TURNO_TRAMITACAO_CHOICES, YES_NO_CHOICES, autor_label,
autor_modal, gerar_hash_arquivo, get_base_url, autor_modal, gerar_hash_arquivo, get_base_url,
montar_row_autor, show_results_filter_set) montar_row_autor, show_results_filter_set)
import sapl
from .email_utils import do_envia_email_confirmacao from .email_utils import do_envia_email_confirmacao
from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm, from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm,
@ -62,6 +62,7 @@ from .models import (AcompanhamentoMateria, Anexada, AssuntoMateria, Autoria,
TipoProposicao, Tramitacao, UnidadeTramitacao) TipoProposicao, Tramitacao, UnidadeTramitacao)
from .signals import tramitacao_signal from .signals import tramitacao_signal
AssuntoMateriaCrud = Crud.build(AssuntoMateria, 'assunto_materia') AssuntoMateriaCrud = Crud.build(AssuntoMateria, 'assunto_materia')
OrigemCrud = Crud.build(Origem, '') OrigemCrud = Crud.build(Origem, '')

6
sapl/templates/search/search.html

@ -54,6 +54,9 @@
{% if result.object.texto_original %} {% if result.object.texto_original %}
<strong>Texto Original:</strong> <a href="{{result.object.texto_original.url}}"> Clique aqui </a></br> <strong>Texto Original:</strong> <a href="{{result.object.texto_original.url}}"> Clique aqui </a></br>
{% endif %}
{% if result.object.texto_articulado.first %}
<strong>Texto Articulado:</strong> <a href="{% url 'sapl.materia:materia_ta' result.object.pk %}"> Clique aqui </a></br>
{% else %} {% else %}
<strong>O texto desta matéria foi removido recentemente. Em breve ela sairá desta listagem.</strong></br> <strong>O texto desta matéria foi removido recentemente. Em breve ela sairá desta listagem.</strong></br>
{% endif %} {% endif %}
@ -74,6 +77,9 @@
<strong> Norma Jurídica: </strong><a href="{% url 'sapl.norma:normajuridica_detail' result.object.pk %}">{{ result.object }}</a></br> <strong> Norma Jurídica: </strong><a href="{% url 'sapl.norma:normajuridica_detail' result.object.pk %}">{{ result.object }}</a></br>
{% if result.object.texto_integral %} {% if result.object.texto_integral %}
<strong>Texto Original:</strong> <a href="{{result.object.texto_integral.url}}"> Clique aqui </a></br> <strong>Texto Original:</strong> <a href="{{result.object.texto_integral.url}}"> Clique aqui </a></br>
{% endif %}
{% if result.object.texto_articulado.first %}
<strong>Texto Articulado:</strong> <a href="{% url 'sapl.norma:norma_ta' result.object.pk %}"> Clique aqui </a></br>
{% else %} {% else %}
<strong>O texto desta norma foi removido recentemente. Em breve ela sairá desta listagem.</strong></br> <strong>O texto desta norma foi removido recentemente. Em breve ela sairá desta listagem.</strong></br>
{% endif %} {% endif %}

Loading…
Cancel
Save