Browse Source

ref buscador modal de Autores c pesq param reversa

pull/739/head
LeandroRoberto 8 years ago
parent
commit
3a3e5fbea7
  1. 81
      sapl/api/forms.py
  2. 78
      sapl/api/serializers.py
  3. 22
      sapl/api/urls.py
  4. 111
      sapl/api/views.py
  5. 11
      sapl/base/forms.py
  6. 9
      sapl/comissoes/models.py
  7. 9
      sapl/materia/views.py
  8. 22
      sapl/parlamentares/models.py
  9. 9
      sapl/protocoloadm/views.py
  10. 19
      sapl/sessao/models.py
  11. 3
      sapl/settings.py
  12. 31
      sapl/static/js/app.js
  13. 6
      sapl/static/styles/app.scss
  14. 17
      sapl/templates/base/autor_form.html
  15. 2
      sapl/urls.py

81
sapl/api/forms.py

@ -0,0 +1,81 @@
from django.contrib.contenttypes.fields import GenericRel
from django.db.models import Q
from django_filters.filters import MethodFilter, ModelChoiceFilter
from rest_framework.filters import FilterSet
from sapl.base.models import Autor, TipoAutor
from sapl.utils import SaplGenericRelation
def autores_models_generic_relations():
models_of_generic_relations = list(map(
lambda x: x.related_model,
filter(
lambda obj: obj.is_relation and
hasattr(obj, 'field') and
isinstance(obj, GenericRel),
Autor._meta.get_fields(include_hidden=True))
))
models = list(map(
lambda x: (x,
list(filter(
lambda field: (
isinstance(
field, SaplGenericRelation) and
field.related_model == Autor),
x._meta.get_fields(include_hidden=True)))),
models_of_generic_relations
))
return models
class AutorChoiceFilterSet(FilterSet):
q = MethodFilter()
tipo = ModelChoiceFilter(queryset=TipoAutor.objects.all())
class Meta:
model = Autor
fields = ['q',
'tipo',
'nome', ]
def filter_q(self, queryset, value):
query = value.split(' ')
if query:
q = Q()
for qtext in query:
if not qtext:
continue
q_fs = Q(nome__icontains=qtext)
order_by = []
for gr in autores_models_generic_relations():
model = gr[0]
sgr = gr[1]
for item in sgr:
if item.related_model != Autor:
continue
flag_order_by = True
for field in item.fields_search:
if flag_order_by:
flag_order_by = False
order_by.append('%s__%s' % (
item.related_query_name(),
field[0])
)
q_fs = q_fs | Q(**{'%s__%s%s' % (
item.related_query_name(),
field[0],
field[1]): qtext})
q = q & q_fs
if q:
queryset = queryset.filter(q).order_by(*order_by)
return queryset

78
sapl/api/serializers.py

@ -1,9 +1,79 @@
from django.contrib.contenttypes.fields import GenericRel
from rest_framework import serializers
from sapl.base.models import Autor
from sapl.utils import SaplGenericRelation
class ChoiceSerializer(serializers.Serializer):
pk = serializers.IntegerField()
display = serializers.SerializerMethodField()
value = serializers.SerializerMethodField()
text = serializers.SerializerMethodField()
def get_text(self, obj):
return obj[1]
def get_value(self, obj):
return obj[0]
class AutorChoiceSerializer(ChoiceSerializer):
def get_text(self, obj):
return obj.nome
def get_value(self, obj):
return obj.id
class Meta:
model = Autor
fields = ['id', 'tipo', 'nome', 'object_id', 'autor_related', 'user']
# Models que apontaram uma GenericRelation com Autor
def autores_models_generic_relations():
models_of_generic_relations = list(map(
lambda x: x.related_model,
filter(
lambda obj: obj.is_relation and
hasattr(obj, 'field') and
isinstance(obj, GenericRel),
Autor._meta.get_fields(include_hidden=True))
))
models = list(map(
lambda x: (x,
list(filter(
lambda field: (
isinstance(
field, SaplGenericRelation) and
field.related_model == Autor),
x._meta.get_fields(include_hidden=True)))),
models_of_generic_relations
))
return models
class AutorObjectRelatedField(serializers.RelatedField):
def to_representation(self, value):
return str(value)
for gr in autores_models_generic_relations():
if isinstance(value, gr[0]):
verbose_name = gr[0]._meta.verbose_name
fields_search = gr[1][0].fields_search
raise Exception(_('Erro na seleção de autor'))
class AutorSerializer(serializers.ModelSerializer):
autor_related = AutorObjectRelatedField(read_only=True)
def get_display(self, obj):
return str(obj)
class Meta:
model = Autor
fields = ['id', 'tipo', 'nome', 'object_id', 'autor_related', 'user']

22
sapl/api/urls.py

@ -1,18 +1,24 @@
from django.conf.urls import url
from sapl.api.views import TipoAutorContentOfModelContentTypeView
from django.conf.urls import url, include
from sapl.api.views import AutorListView
from .apps import AppConfig
app_name = AppConfig.name
# router = DefaultRouter()
urlpatterns = [
url(r'^autor/possiveis-pelo-tipo/(?P<pk>[0-9]+)$',
TipoAutorContentOfModelContentTypeView.as_view(),
name='autores_possiveis_pelo_tipo'),
# urlpatterns += router.urls
urlpatterns_api = [
# url(r'^$', api_root),
url(r'^autor',
AutorListView.as_view(),
name='autor_list'),
]
# urlpatterns += router.urls
urlpatterns = [
url(r'^api/', include(urlpatterns_api))
]

111
sapl/api/views.py

@ -1,50 +1,109 @@
from django.db.models import Q
from django.http import Http404
from rest_framework.generics import ListAPIView, get_object_or_404
from rest_framework.filters import DjangoFilterBackend
from rest_framework.generics import ListAPIView
from rest_framework.permissions import IsAuthenticated
from rest_framework.viewsets import ModelViewSet
from sapl.api.serializers import ChoiceSerializer
from sapl.api.forms import AutorChoiceFilterSet
from sapl.api.serializers import ChoiceSerializer, AutorSerializer,\
AutorChoiceSerializer
from sapl.base.models import Autor, TipoAutor
from sapl.utils import SaplGenericRelation
class TipoAutorContentOfModelContentTypeView(ListAPIView):
serializer_class = ChoiceSerializer
class AutorListView(ListAPIView):
"""
Listagem de Autores com filtro para autores cadastrados
e/ou possíveis autores.
- tipo - chave primária do Tipo de Autor a ser filtrado
- provaveis - variável sem relevância de valor, porém, sua presença
faz com que a AutorListView
mostre a lista de provaveis Autores armazenados segundo o
ContentType associado ao Tipo de Autor via relacionamento
genérico.
- q - busca textual no nome do Autor ou em fields_search
declarados no field SaplGenericRelation das GenericFks
A busca textual acontece via django-filter se não
estiver presente a variável `provaveis`. Em caso
contrário, o django-filter é desativado e a busca é feita
no model do ContentType associado ao tipo.
"""
# FIXME aplicar permissão correta de usuário
permission_classes = (IsAuthenticated,)
queryset = TipoAutor.objects.all()
model = TipoAutor
serializer_class = AutorSerializer
queryset = Autor.objects.all()
model = Autor
def get(self, request, *args, **kwargs):
"""
desativa o django-filter se a busca for por provaveis autores
"""
provaveis = 'provaveis' in request.GET
self.filter_class = None if provaveis else AutorChoiceFilterSet
self.filter_backends = [] if provaveis else [DjangoFilterBackend]
self.serializer_class = ChoiceSerializer\
if provaveis else AutorChoiceSerializer
return ListAPIView.get(self, request, *args, **kwargs)
def get_queryset(self):
queryset = ModelViewSet.get_queryset(self)
queryset = ListAPIView.get_queryset(self)
if not self.kwargs['pk']:
raise Http404()
if self.filter_backends:
return queryset
params = {'content_type__isnull': False}
tipo = ''
try:
tipo = int(self.request.GET.get('tipo', ''))
if tipo:
params['id'] = tipo
except:
pass
obj = get_object_or_404(queryset, pk=self.kwargs['pk'])
tipos = TipoAutor.objects.filter(**params)
if not obj.content_type:
if not tipos.exists() and tipo:
raise Http404()
q = self.request.GET.get('q', '').strip()
r = []
for tipo in tipos:
q = self.request.GET.get('q', '').strip()
model_class = obj.content_type.model_class()
model_class = tipo.content_type.model_class()
fields = list(filter(
lambda field: isinstance(field, SaplGenericRelation) and
field.related_model == Autor,
model_class._meta.get_fields(include_hidden=True)))
fields = list(filter(
lambda field: isinstance(field, SaplGenericRelation) and
field.related_model == Autor,
model_class._meta.get_fields(include_hidden=True)))
assert len(fields) == 1
# retirar assert
assert len(fields) == 1
fields_search = fields[0].fields_search
qs = model_class.objects.all().order_by(
fields[0].fields_search[0][0])
if q:
q_filter = Q()
for fs in fields_search:
q_filter |= Q(**{'%s__icontains' % fs: q})
if q:
for item in fields:
if item.related_model != Autor:
continue
q_fs = Q()
for field in item.fields_search:
q_fs = q_fs | Q(**{'%s%s' % (
field[0],
field[1]): q})
q_filter = q_filter & q_fs
qs = qs.filter(q_filter).distinct(
fields[0].fields_search[0][0])
qs = qs.values_list('id', fields[0].fields_search[0][0])
return model_class.objects.filter(q_filter)
else:
return model_class.objects.all()
r += list(qs)
r.sort(key=lambda x: x[1])
return r

11
sapl/base/forms.py

@ -228,9 +228,6 @@ class AutorForm(ModelForm):
User = get_user_model()
cd = self.cleaned_data
if 'username' not in cd or not cd['username']:
raise ValidationError(_('O username deve ser informado.'))
if 'action_user' not in cd or not cd['action_user']:
raise ValidationError(_('Informe se o Autor terá usuário '
'vinculado para acesso ao Sistema.'))
@ -292,6 +289,10 @@ class AutorForm(ModelForm):
'"Criar novo Usuário".') % cd['username'])
if cd['action_user'] != 'N':
if 'username' not in cd or not cd['username']:
raise ValidationError(_('O username deve ser informado.'))
if qs_autor.filter(user__username=cd['username']).exists():
raise ValidationError(
_('Já existe um Autor para este usuário.'))
@ -333,7 +334,6 @@ class AutorForm(ModelForm):
@transaction.atomic
def save(self, commit=False):
print('aqui')
autor = super(AutorForm, self).save(commit)
user_old = autor.user if autor.user_id else None
@ -349,6 +349,7 @@ class AutorForm(ModelForm):
u.set_password(self.cleaned_data['senha'])
# Define usuário como ativo em ambiente de desenvolvimento
# pode logar sem a necessidade de passar pela validação de email
# troque par False para testar o envio de email em desenvolvimento
u.is_active = settings.DEBUG
u.save()
autor.user = u
@ -384,7 +385,7 @@ class AutorForm(ModelForm):
elif self.cleaned_data['status_user'] == 'R':
user_old.groups.remove(grupo)
else:
elif user_old:
user_old.groups.remove(grupo)
return autor

9
sapl/comissoes/models.py

@ -80,14 +80,19 @@ class Comissao(models.Model):
choices=YES_NO_CHOICES,
verbose_name=_('Comissão Ativa?'))
autor = SaplGenericRelation(Autor, fields_search=('nome', 'sigla'))
autor = SaplGenericRelation(Autor,
related_query_name='comissao_set',
fields_search=(
('nome', '__icontains'),
('sigla', '__icontains')
))
class Meta:
verbose_name = _('Comissão')
verbose_name_plural = _('Comissões')
def __str__(self):
return self.nome
return self.sigla + ' - ' + self.nome
class Periodo(models.Model): # PeriodoCompComissao

9
sapl/materia/views.py

@ -33,13 +33,10 @@ from sapl.materia.forms import AnexadaForm, LegislacaoCitadaForm
from sapl.norma.models import LegislacaoCitada
from sapl.utils import (TURNO_TRAMITACAO_CHOICES, YES_NO_CHOICES, autor_label,
autor_modal, gerar_hash_arquivo, get_base_url,
<<<<<<< 3276eb12726b741df770d5a6ed2a9a1a83c15849
permissoes_autor, permissoes_materia,
permissoes_protocoloadm, permission_required_for_app)
=======
montar_row_autor, permissoes_autor, permissoes_materia,
permissoes_protocoloadm)
>>>>>>> Conc refatoração no Cada de Autor e Tipos de Autor
permissoes_protocoloadm, permission_required_for_app,
montar_row_autor)
from .forms import (AcessorioEmLoteFilterSet, AcompanhamentoMateriaForm,
ConfirmarProposicaoForm, DocumentoAcessorioForm,

22
sapl/parlamentares/models.py

@ -265,8 +265,15 @@ class Parlamentar(models.Model):
# campo conceitual de reversão genérica para o model Autor que dá a
# o meio possível de localização de tipos de autores.
autor = SaplGenericRelation(Autor, fields_search=('nome_completo',
'nome_parlamentar'))
autor = SaplGenericRelation(
Autor,
related_query_name='parlamentar_set',
fields_search=(
# na primeira posição dever ser campo simples sem __
('nome_completo', '__icontains'),
('nome_parlamentar', '__icontains'),
('filiacao__partido__sigla', '__icontains'),
))
class Meta:
verbose_name = _('Parlamentar')
@ -455,8 +462,15 @@ class Frente(models.Model):
# campo conceitual de reversão genérica para o model Autor que dá a
# o meio possível de localização de tipos de autores.
autor = SaplGenericRelation(Autor, fields_search=('nome',
'descricao'))
autor = SaplGenericRelation(
Autor,
related_query_name='frente_set',
fields_search=(
('nome', '__icontains'),
('descricao', '__icontains'),
('parlamentares__filiacao__partido__sigla', '__icontains'),
('parlamentares__filiacao__partido__nome', '__icontains'),
))
class Meta:
verbose_name = _('Frente')

9
sapl/protocoloadm/views.py

@ -1,5 +1,5 @@
import json
from datetime import date, datetime
import json
from braces.views import FormValidMessageMixin
from django.contrib import messages
@ -31,6 +31,7 @@ from .models import (Autor, DocumentoAcessorioAdministrativo,
StatusTramitacaoAdministrativo,
TipoDocumentoAdministrativo, TramitacaoAdministrativo)
TipoDocumentoAdministrativoCrud = CrudAux.build(
TipoDocumentoAdministrativo, '')
@ -605,11 +606,13 @@ def pesquisa_autores(request):
if request.method == 'GET':
q = request.GET.get('q', '')
autor = Autor.objects.filter(
"""autor = Autor.objects.filter(
Q(nome__icontains=q) |
Q(parlamentar__nome_parlamentar__icontains=q) |
Q(comissao__nome__icontains=q)
)
)"""
autor = Autor.objects.filter(nome__icontains=q)
autores = []

19
sapl/sessao/models.py

@ -42,8 +42,13 @@ class Bancada(models.Model):
# campo conceitual de reversão genérica para o model Autor que dá a
# o meio possível de localização de tipos de autores.
autor = SaplGenericRelation(Autor, fields_search=('nome',
'descricao'))
autor = SaplGenericRelation(Autor, related_query_name='bancada_set',
fields_search=(
('nome', '__icontains'),
('descricao', '__icontains'),
('partido__sigla', '__icontains'),
('partido__nome', '__icontains'),
))
class Meta:
verbose_name = _('Bancada')
@ -350,8 +355,14 @@ class Bloco(models.Model):
# campo conceitual de reversão genérica para o model Autor que dá a
# o meio possível de localização de tipos de autores.
autor = SaplGenericRelation(Autor, fields_search=('nome',
'descricao'))
autor = SaplGenericRelation(Autor,
related_query_name='bloco_set',
fields_search=(
('nome', '__icontains'),
('descricao', '__icontains'),
('partidos__sigla', '__icontains'),
('partidos__nome', '__icontains'),
))
class Meta:
verbose_name = _('Bloco')

3
sapl/settings.py

@ -93,7 +93,7 @@ MIDDLEWARE_CLASSES = (
REST_FRAMEWORK = {
"DEFAULT_RENDERER_CLASSES": (
"rest_framework.renderers.JSONRenderer",
# "rest_framework.renderers.BrowsableAPIRenderer",
#"rest_framework.renderers.BrowsableAPIRenderer",
),
"DEFAULT_PARSER_CLASSES": (
"rest_framework.parsers.JSONParser",
@ -102,7 +102,6 @@ REST_FRAMEWORK = {
"rest_framework.permissions.IsAuthenticated",
),
"DEFAULT_PERMISSION_CLASSES": (
# "rest_framework.permissions.IsAuthenticated",
"sapl.api.permissions.DjangoModelPermissions",
),
"DEFAULT_AUTHENTICATION_CLASSES": (

31
sapl/static/js/app.js

@ -90,28 +90,25 @@ function autorModal() {
$("#pesquisar").click(function() {
var query = $("#q").val()
$.get("/protocoloadm/pesquisar-autor?q="+ query, function(
data, status){
$("#div-resultado").children().remove();
$.get("/api/autor?q=" + query, function(data, status) {
$("#div-resultado").children().remove();
if (data.pagination.total_entries == 0) {
$("#selecionar").attr("hidden", "hidden");
$("#div-resultado").html(
"<span class='alert'><strong>Nenhum resultado</strong></span>");
return;
}
if (data.length == 0) {
$("#selecionar").attr("hidden", "hidden");
$("#div-resultado").html(
"<span class='alert'><strong>Nenhum resultado</strong></span>");
return;
}
var select = $(
'<select id="resultados" \
style="min-width: 90%; max-width:90%;" size="5"/>');
var select = $(
'<select id="resultados" \
style="min-width: 90%; max-width:90%;" size="5"/>');
data.models.forEach(function(item, index) {
select.append($("<option>").attr('value', item.value).text(item.text));
});
for (i = 0; i < data.length; i++) {
id = data[i][0];
nome = data[i][1];
select.append($("<option>").attr('value',id).text(nome));
}
$("#div-resultado").append("<br/>").append(select);
$("#selecionar").removeAttr("hidden", "hidden");

6
sapl/static/styles/app.scss

@ -24,12 +24,6 @@ nav {
background-color: $link-hover-color;
}
}
&:first-child {
& > a {
padding-left: 0px;
padding-right: 0px;
}
}
&:nth-child(2) {
& > .dropdown-menu {
right: auto;

17
sapl/templates/base/autor_form.html

@ -26,19 +26,20 @@ $(document).ready(function(){
}
var update_search = function(pk, atualizar=true) {
var q = $('#id_q').val();
var url = '{% url 'sapl.api:autores_possiveis_pelo_tipo' 0 %}'
url = url.replace('0', pk);
var url = '{% url 'sapl.api:autor_list'%}'
var formData = {
'q' : q,
'format' : 'json',
'q' : q,
'tipo' : pk,
'provaveis' : ''
}
$.get(url, formData).done(function(data) {
active('pesquisa');
if (atualizar) {
var radios = $("#div_id_autor_related .controls").html('');
data.models.forEach(function (val, index) {
var html_radio = '<label class="radio"><span class="icons"><span class="first-icon"></span><span class="second-icon"></span></span><input type="radio" name="autor_related" id="id_autor_related_'+index+'" value="'+val.pk+'">'+val.display+'</label>';
var html_radio = '<label class="radio"><span class="icons"><span class="first-icon"></span><span class="second-icon"></span></span><input type="radio" name="autor_related" id="id_autor_related_'+index+'" value="'+val.value+'">'+val.text+'</label>';
radios.append(html_radio);
});
@ -66,6 +67,7 @@ $(document).ready(function(){
active('nome');
});
}
$('#id_tipo').change(function(event) {
if (event.target.selectedIndex == 0) {
$('#id_nome, #id_q').val('');
@ -77,10 +79,12 @@ $(document).ready(function(){
update_search(pk, false)
}
});
$('.btn-filtrar-autor').click(function(event) {
var pk = $('#id_tipo').val();
update_search(pk);
});
$('input[name=action_user]').change(function(event) {
if (!this.checked)
return;
@ -115,10 +119,9 @@ $(document).ready(function(){
|| (event.target.value == 'C' && username.attr('data') != ''))
$('.radiogroup-status').removeClass('hidden');
}
}
});
$('input[name=username]').keyup(function(event) {
if (!flag_create)
if (this.getAttribute('data') != '' && this.value != this.getAttribute('data'))

2
sapl/urls.py

@ -52,7 +52,7 @@ urlpatterns = [
# so that base /sistema/ url doesn't capture its children
url(r'', include(sapl.base.urls)),
url(r'^api/', include(sapl.api.urls)),
url(r'', include(sapl.api.urls)),
]

Loading…
Cancel
Save