Browse Source

adiciona Textos Articulados na pesquisa textual

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

157
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:
raise Exception
data = super(DocumentoAcessorioIndex, self).prepare(obj) data = []
arquivo = getattr(obj, self.filename) for attr in self.model_attr:
if not hasattr(obj, attr):
raise Exception
if arquivo: value = getattr(obj, attr)
if not os.path.exists(arquivo.path):
return self.prepared_data
if not os.path.splitext(arquivo.path)[1][:1]: if not value:
return self.prepared_data continue
# Em ambiente de produção utiliza-se o SOLR if isinstance(value, FieldFile):
if SOLR_URL: if not os.path.exists(value.path):
try: continue
extracted_data = self.solr_extraction(arquivo)
except Exception:
self.print_error(arquivo)
return self.prepared_data
# Em ambiente de DEV utiliza-se o Whoosh if not os.path.splitext(value.path)[1][:1]:
# Como ele não possui extração, faz-se uso do textract continue
else:
try:
extracted_data = self.whoosh_extraction(arquivo)
except ExtensionNotSupported as e:
print(str(e))
logger.error(str(e))
return self.prepared_data
except Exception:
self.print_error(arquivo)
return self.prepared_data
# Now we'll finally perform the template processing to render the # Em ambiente de produção utiliza-se o SOLR
# text field with *all* of our metadata visible for templating: if SOLR_URL:
t = loader.select_template(( try:
'search/indexes/' + self.template_name, )) data.append(self.solr_extraction(value))
data['text'] = t.render({'object': obj, except Exception:
'extracted': extracted_data}) self.print_error(value)
return data # Em ambiente de DEV utiliza-se o Whoosh
# Como ele não possui extração, faz-se uso do textract
else:
try:
data.append(self.whoosh_extraction(value))
except ExtensionNotSupported as e:
print(str(e))
logger.error(str(e))
except Exception:
self.print_error(value)
return self.prepared_data elif hasattr(value, 'model') and value.model == TextoArticulado:
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))
class MateriaLegislativaIndex(DocumentoAcessorioIndex): return ' '.join(data)
text = indexes.CharField(document=True, use_template=True)
filename = 'texto_original' def prepare_template(self, obj):
model = MateriaLegislativa app_label, model_name = get_model_ct_tuple(obj)
template_name = 'materia/materialegislativa_text.txt' template_names = ['search/indexes/%s/%s_%s.txt' %
(app_label, model_name, self.instance_name)]
t = loader.select_template(template_names)
return t.render({'object': obj,
'extracted': self.extract_data(obj)})
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, '')

8
sapl/templates/search/search.html

@ -54,11 +54,14 @@
{% 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 %}
</p> </p>
{% elif result.object|search_get_model == 'd' %} {% elif result.object|search_get_model == 'd' %}
<p> <p>
<strong> Documento Acessório: </strong><a href="{% url 'sapl.materia:documentoacessorio_detail' result.object.pk %}">{{ result.object }}</a></br> <strong> Documento Acessório: </strong><a href="{% url 'sapl.materia:documentoacessorio_detail' result.object.pk %}">{{ result.object }}</a></br>
@ -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