Browse Source

Ajusta front para busca por possiveis autores

Ajusta front e implementa SaplGenericRelation, uma customização que
adiciona o atributo fields_search que possibilita passar para qualquer
implementação de busca quais são os campos de busca padrão do do
GenericRelation
pull/739/head
LeandroRoberto 8 years ago
parent
commit
cd7bf6f752
  1. 26
      sapl/api/views.py
  2. 33
      sapl/base/forms.py
  3. 26
      sapl/base/migrations/0024_auto_20161010_1002.py
  4. 6
      sapl/base/models.py
  5. 4
      sapl/comissoes/models.py
  6. 6
      sapl/parlamentares/models.py
  7. 39
      sapl/templates/base/autor_form.html
  8. 10
      sapl/utils.py

26
sapl/api/views.py

@ -1,3 +1,4 @@
from django.db.models import Q
from django.http import Http404 from django.http import Http404
from rest_framework import mixins, viewsets from rest_framework import mixins, viewsets
from rest_framework.generics import ListAPIView, GenericAPIView,\ from rest_framework.generics import ListAPIView, GenericAPIView,\
@ -8,6 +9,7 @@ from rest_framework.viewsets import ModelViewSet
from sapl.api.serializers import ChoiceSerializer from sapl.api.serializers import ChoiceSerializer
from sapl.base.models import Autor, TipoAutor from sapl.base.models import Autor, TipoAutor
from sapl.utils import SaplGenericRelation
class TipoAutorContentOfModelContentTypeView(ListAPIView): class TipoAutorContentOfModelContentTypeView(ListAPIView):
@ -27,10 +29,24 @@ class TipoAutorContentOfModelContentTypeView(ListAPIView):
if not obj.content_type: if not obj.content_type:
raise Http404 raise Http404
q = self.request.GET.get('q', None) q = self.request.GET.get('q', '').strip()
if not q: model_class = obj.content_type.model_class()
return []
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
fields_search = fields[0].fields_search
if q:
q_filter = Q()
for fs in fields_search:
q_filter |= Q(**{'%s__icontains' % fs: q})
return model_class.objects.filter(q_filter)[:10]
else: else:
return obj.content_type.model_class().objects.filter( return model_class.objects.all()[:10]
nome__icontains=q)[:10]

33
sapl/base/forms.py

@ -85,21 +85,22 @@ class AutorForm(ModelForm):
q = forms.CharField( q = forms.CharField(
max_length=50, required=False, max_length=50, required=False,
label='Pesquise o nome do Autor com o tipo Selecionado') label='Pesquise o nome do Autor com o '
content_object = forms.ChoiceField(label='', 'tipo Selecionado e marque o escolhido.')
required=False, autor_related = forms.ChoiceField(label='',
widget=forms.RadioSelect()) required=False,
widget=forms.RadioSelect())
class Meta: class Meta:
model = Autor model = Autor
fields = ['tipo', fields = ['tipo',
'nome', 'nome',
'content_object', 'autor_related',
'q'] 'q']
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
content_object = Div( autor_related = Div(
FieldWithButtons( FieldWithButtons(
Field('q', Field('q',
@ -108,20 +109,16 @@ class AutorForm(ModelForm):
StrictButton( StrictButton(
_('Filtrar'), css_class='btn-default btn-filtrar-autor', _('Filtrar'), css_class='btn-default btn-filtrar-autor',
type='button')), type='button')),
Field('autor_related'),
Field('content_object'),
css_class='hidden', css_class='hidden',
data_action='create', data_action='create',
data_application='AutorSearch', data_application='AutorSearch',
data_field='content_object') data_field='autor_related')
row1 = to_row([ row1 = to_row([
('tipo', 4), ('tipo', 4),
('nome', 8), ('nome', 8),
(content_object, 8), (autor_related, 8),
]) ])
@ -130,11 +127,11 @@ class AutorForm(ModelForm):
super(AutorForm, self).__init__(*args, **kwargs) super(AutorForm, self).__init__(*args, **kwargs)
self.fields['content_object'].choices = [('1', 'teste')] self.fields['autor_related'].choices = []
if self.instance and self.instance.content_object: if self.instance and self.instance.autor_related:
self.fields['content_object'].choices = [ self.fields['autor_related'].choices = [
(self.instance.content_object.pk, (self.instance.autor_related.pk,
self.instance.content_object)] self.instance.autor_related)]
def valida_igualdade(self, texto1, texto2, msg): def valida_igualdade(self, texto1, texto2, msg):
if texto1 != texto2: if texto1 != texto2:

26
sapl/base/migrations/0024_auto_20161010_1002.py

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-10-10 13:02
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('base', '0023_auto_20161009_1852'),
]
operations = [
migrations.AlterField(
model_name='autor',
name='nome',
field=models.CharField(blank=True, max_length=50, verbose_name='Nome do Autor'),
),
migrations.AlterField(
model_name='autor',
name='tipo',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='base.TipoAutor', verbose_name='Tipo do Autor'),
),
]

6
sapl/base/models.py

@ -160,7 +160,7 @@ class Autor(models.Model):
blank=True, null=True, default=None) blank=True, null=True, default=None)
object_id = models.PositiveIntegerField( object_id = models.PositiveIntegerField(
blank=True, null=True, default=None) blank=True, null=True, default=None)
content_object = GenericForeignKey('content_type', 'object_id') autor_related = GenericForeignKey('content_type', 'object_id')
nome = models.CharField( nome = models.CharField(
max_length=50, blank=True, verbose_name=_('Nome do Autor')) max_length=50, blank=True, verbose_name=_('Nome do Autor'))
@ -174,8 +174,8 @@ class Autor(models.Model):
def __str__(self): def __str__(self):
if self.content_object: if self.autor_related:
return str(self.content_object) return str(self.autor_related)
else: else:
if str(self.cargo): if str(self.cargo):
return _('%(nome)s - %(cargo)s') % { return _('%(nome)s - %(cargo)s') % {

4
sapl/comissoes/models.py

@ -6,7 +6,7 @@ from model_utils import Choices
from sapl.base.models import Autor from sapl.base.models import Autor
from sapl.parlamentares.models import Parlamentar from sapl.parlamentares.models import Parlamentar
from sapl.utils import YES_NO_CHOICES from sapl.utils import YES_NO_CHOICES, SaplGenericRelation
class TipoComissao(models.Model): class TipoComissao(models.Model):
@ -81,7 +81,7 @@ class Comissao(models.Model):
choices=YES_NO_CHOICES, choices=YES_NO_CHOICES,
verbose_name=_('Comissão Ativa?')) verbose_name=_('Comissão Ativa?'))
autor = GenericRelation(Autor) autor = SaplGenericRelation(Autor, fields_search=('nome', 'sigla'))
class Meta: class Meta:
verbose_name = _('Comissão') verbose_name = _('Comissão')

6
sapl/parlamentares/models.py

@ -8,7 +8,7 @@ from model_utils import Choices
from sapl.base.models import Autor from sapl.base.models import Autor
from sapl.utils import (INDICADOR_AFASTAMENTO, UF, YES_NO_CHOICES, from sapl.utils import (INDICADOR_AFASTAMENTO, UF, YES_NO_CHOICES,
intervalos_tem_intersecao, intervalos_tem_intersecao,
restringe_tipos_de_arquivo_img) restringe_tipos_de_arquivo_img, SaplGenericRelation)
class Legislatura(models.Model): class Legislatura(models.Model):
@ -264,7 +264,9 @@ class Parlamentar(models.Model):
verbose_name=_('Fotografia'), verbose_name=_('Fotografia'),
validators=[restringe_tipos_de_arquivo_img]) validators=[restringe_tipos_de_arquivo_img])
autor = GenericRelation(Autor) # campo conceitual de reversão genérica para o model Autor
autor = SaplGenericRelation(Autor, fields_search=('nome_completo',
'nome_parlamentar'))
class Meta: class Meta:
verbose_name = _('Parlamentar') verbose_name = _('Parlamentar')

39
sapl/templates/base/autor_form.html

@ -7,10 +7,10 @@
$(document).ready(function(){ $(document).ready(function(){
var active = function(str) { var active = function(str) {
if (str == 'nome') { if (str == 'nome') {
$('#id_q').val(''); $('#id_nome, #id_q').val('');
$('#div_id_nome').removeClass('hidden'); $('#div_id_nome').removeClass('hidden');
$("[data-application='AutorSearch']").addClass('hidden'); $("[data-application='AutorSearch']").addClass('hidden');
$("#div_id_content_object .controls").html(''); $("#div_id_autor_related .controls").html('');
} }
else { else {
$('#id_nome').val(''); $('#id_nome').val('');
@ -18,7 +18,7 @@ $(document).ready(function(){
$("[data-application='AutorSearch']").removeClass('hidden'); $("[data-application='AutorSearch']").removeClass('hidden');
} }
} }
var update_search = function(pk) { var update_search = function(pk, atualizar=true) {
var q = $('#id_q').val(); var q = $('#id_q').val();
var url = '{% url 'sapl.api:autores_possiveis_pelo_tipo' 0 %}' var url = '{% url 'sapl.api:autores_possiveis_pelo_tipo' 0 %}'
url = url.replace('0', pk); url = url.replace('0', pk);
@ -28,15 +28,29 @@ $(document).ready(function(){
'format' : 'json', 'format' : 'json',
} }
$.get(url, formData).done(function(data) { $.get(url, formData).done(function(data) {
var radios = $("#div_id_content_object .controls").html(''); active('pesquisa');
active('pesquisa'); if (atualizar) {
data.forEach(function (val, index) { var radios = $("#div_id_autor_related .controls").html('');
var html_radio = '<div class="radio"><label><input type="radio" name="content_object" id="id_content_object_'+index+'" value="'+val.pk+'">'+val.display+'</label></div>'; data.forEach(function (val, index) {
radios.append(html_radio); var html_radio = '<div class="radio"><label><input type="radio" name="autor_related" id="id_autor_related_'+index+'" value="'+val.pk+'">'+val.display+'</label></div>';
radios.append(html_radio);
});
if (data.length > 1) {
$('input[name=autor_related]').change(function(event){
$('#id_q').val(event.target.parentElement.textContent);
//$('input[name=autor_related]:not(:checked)').closest('.radio').remove();
});
}
else {
$('input[name=autor_related]').prop('checked', 'checked')
}
}
else{
$('#id_nome, #id_q').val('');
}
}).fail(function(data) {
active('nome');
}); });
}).fail(function(data) {
active('nome');
});
} }
$('#id_tipo').change(function(event) { $('#id_tipo').change(function(event) {
@ -46,7 +60,8 @@ $(document).ready(function(){
} }
else { else {
var pk = this[event.target.selectedIndex].value; var pk = this[event.target.selectedIndex].value;
update_search(pk); $('input[name=autor_related]').closest('.radio').remove();
update_search(pk, false)
} }
}); });
$('.btn-filtrar-autor').click(function(event) { $('.btn-filtrar-autor').click(function(event) {

10
sapl/utils.py

@ -10,6 +10,7 @@ from django.conf import settings
from django.contrib import admin from django.contrib import admin
from django.contrib.auth.decorators import user_passes_test from django.contrib.auth.decorators import user_passes_test
from django.contrib.auth.models import Permission from django.contrib.auth.models import Permission
from django.contrib.contenttypes.fields import GenericRelation
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied, ValidationError from django.core.exceptions import PermissionDenied, ValidationError
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -55,6 +56,15 @@ autor_modal = '''
''' '''
class SaplGenericRelation(GenericRelation):
def __init__(self, to, fields_search=(), **kwargs):
assert fields_search
self.fields_search = fields_search
super().__init__(to, **kwargs)
class ImageThumbnailFileInput(ClearableFileInput): class ImageThumbnailFileInput(ClearableFileInput):
template_name = 'floppyforms/image_thumbnail.html' template_name = 'floppyforms/image_thumbnail.html'

Loading…
Cancel
Save