From d2ccad6bd79eb414ab69a6d6b03e6ce216aa1677 Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Tue, 15 Mar 2016 13:34:08 -0300 Subject: [PATCH 01/27] WIP --- base/forms.py | 2 +- materia/models.py | 6 +++-- parlamentares/forms.py | 5 +++- parlamentares/models.py | 5 ++-- parlamentares/views.py | 17 ++++++------ sapl/utils.py | 57 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 77 insertions(+), 15 deletions(-) diff --git a/base/forms.py b/base/forms.py index 50161fb8c..f37f886ac 100644 --- a/base/forms.py +++ b/base/forms.py @@ -78,7 +78,7 @@ class CasaLegislativaTabelaAuxForm(ModelForm): row3, row4, row5, - HTML("""{% if form.logotipo.value %} + HTML("""{% if not form.fotografia.errors and form.fotografia.value %}

diff --git a/materia/models.py b/materia/models.py index 1d6f96d5c..a9e864931 100644 --- a/materia/models.py +++ b/materia/models.py @@ -4,7 +4,8 @@ from model_utils import Choices from comissoes.models import Comissao from parlamentares.models import Parlamentar, Partido -from sapl.utils import RANGE_ANOS, YES_NO_CHOICES, xstr +from sapl.utils import (restringe_tipos_de_arquivo_txt, + RANGE_ANOS, YES_NO_CHOICES, xstr) class TipoMateriaLegislativa(models.Model): @@ -457,7 +458,8 @@ class Proposicao(models.Model): blank=True, null=True, upload_to=texto_upload_path, - verbose_name=_('Texto Original (PDF)')) + verbose_name=_('Texto Original (PDF)'), + validators=[restringe_tipos_de_arquivo_txt]) class Meta: verbose_name = _('Proposição') diff --git a/parlamentares/forms.py b/parlamentares/forms.py index 9faa5df27..4cf589023 100644 --- a/parlamentares/forms.py +++ b/parlamentares/forms.py @@ -131,7 +131,9 @@ class ParlamentaresForm (ModelForm): row1, row2, row3, row4, row5, row6, row7, row8, row9, row10, row11, row12, row13, - HTML("""{% if form.fotografia.value %} + HTML(""" + {% if not form.fotografia.errors %} + {% if form.fotografia.value %}

@@ -140,6 +142,7 @@ class ParlamentaresForm (ModelForm): id="remover" class="btn btn-warning" value="Remover Foto"/> + {% endif %} {% endif %}""", ), row14, form_actions()) diff --git a/parlamentares/models.py b/parlamentares/models.py index a1055602d..6842ced10 100644 --- a/parlamentares/models.py +++ b/parlamentares/models.py @@ -4,7 +4,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from model_utils import Choices -from sapl.utils import UF, YES_NO_CHOICES +from sapl.utils import restringe_tipos_de_arquivo_img, UF, YES_NO_CHOICES class Legislatura(models.Model): @@ -241,7 +241,8 @@ class Parlamentar(models.Model): blank=True, null=True, upload_to=foto_upload_path, - verbose_name=_('Fotografia')) + verbose_name=_('Fotografia'), + validators=[restringe_tipos_de_arquivo_img]) class Meta: verbose_name = _('Parlamentar') diff --git a/parlamentares/views.py b/parlamentares/views.py index b6803f182..7ff036d5e 100644 --- a/parlamentares/views.py +++ b/parlamentares/views.py @@ -3,7 +3,7 @@ import os from django.contrib import messages from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ -from django.views.generic import FormView +from django.views.generic import CreateView, FormView from crud import Crud @@ -139,8 +139,9 @@ class ParlamentaresCadastroView(FormView): {'form': form, 'legislatura_id': pk}) -class ParlamentaresEditarView(FormView): +class ParlamentaresEditarView(UpdateView): template_name = "parlamentares/parlamentares_cadastro.html" + form_class = ParlamentaresForm def get_success_url(self): return reverse('parlamentares') @@ -155,15 +156,14 @@ class ParlamentaresEditarView(FormView): def post(self, request, *args, **kwargs): pk = kwargs['pk'] parlamentar = Parlamentar.objects.get(pk=pk) - form = ParlamentaresEditForm(request.POST, instance=parlamentar) + + form = ParlamentaresEditForm(request.POST, + request.FILES, + instance=parlamentar) if form.is_valid(): if 'salvar' in request.POST: - parlamentar = form.save(commit=False) - if 'fotografia' in request.FILES: - parlamentar.fotografia = request.FILES['fotografia'] - parlamentar.biografia = form.data['biografia'] - parlamentar.save() + form.save() elif 'excluir' in request.POST: Mandato.objects.get(parlamentar=parlamentar).delete() parlamentar.delete() @@ -172,7 +172,6 @@ class ParlamentaresEditarView(FormView): os.unlink(parlamentar.fotografia.path) except OSError: pass # Should log this error!!!!! - parlamentar = form.save(commit=False) parlamentar.fotografia = None parlamentar.save() return self.form_valid(form) diff --git a/sapl/utils.py b/sapl/utils.py index f5707d197..83a3fc820 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -1,10 +1,13 @@ from datetime import date + from functools import wraps from django.apps import apps from django.contrib import admin +from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ +import magic autor_label = '''
@@ -119,3 +122,57 @@ UF = [ ] RANGE_ANOS = [(year, year) for year in range(date.today().year, 1889, -1)] + +TIPOS_TEXTO_PERMITIDOS = ( + 'application/vnd.oasis.opendocument.text', + 'application/x-vnd.oasis.opendocument.text', + 'application/pdf', + 'application/x-pdf', + 'application/acrobat', + 'applications/vnd.pdf', + 'text/pdf', + 'text/x-pdf', + 'text/plain', + 'application/txt', + 'browser/internal', + 'text/anytext', + 'widetext/plain', + 'widetext/paragraph', + 'application/msword', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', +) + +TIPOS_IMG_PERMITIDOS = ( + 'image/jpeg', + 'image/jpg', + 'image/jpe_', + 'image/pjpeg', + 'image/vnd.swiftview-jpeg', + 'application/jpg', + 'application/x-jpg', + 'image/pjpeg', + 'image/pipeg', + 'image/vnd.swiftview-jpeg', + 'image/x-xbitmap', + 'image/bmp', + 'image/x-bmp', + 'image/x-bitmap', + 'image/png', + 'application/png', + 'application/x-png', +) + + +def fabrica_validador_de_tipos_de_arquivo(lista): + + def restringe_tipos_de_arquivo(value): + mime = magic.from_buffer(value.read(), mime=True) + mime = mime.decode() + if mime not in lista: + raise ValidationError(_('Tipo de arquivo não suportado')) + return restringe_tipos_de_arquivo + +restringe_tipos_de_arquivo_txt = fabrica_validador_de_tipos_de_arquivo( + TIPOS_TEXTO_PERMITIDOS) +restringe_tipos_de_arquivo_img = fabrica_validador_de_tipos_de_arquivo( + TIPOS_IMG_PERMITIDOS) From 2848a9826cf4a5f59fa5bed72a1b7c0dd1e71792 Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Tue, 15 Mar 2016 13:36:26 -0300 Subject: [PATCH 02/27] WIP --- parlamentares/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parlamentares/views.py b/parlamentares/views.py index 7ff036d5e..b34c5f507 100644 --- a/parlamentares/views.py +++ b/parlamentares/views.py @@ -139,7 +139,7 @@ class ParlamentaresCadastroView(FormView): {'form': form, 'legislatura_id': pk}) -class ParlamentaresEditarView(UpdateView): +class ParlamentaresEditarView(FormView): template_name = "parlamentares/parlamentares_cadastro.html" form_class = ParlamentaresForm From 490fffbf4e0e50be52d47056821e7f626ce76dcd Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Tue, 15 Mar 2016 13:34:08 -0300 Subject: [PATCH 03/27] =?UTF-8?q?Refatora=20edi=C3=A7=C3=A3o=20de=20parlam?= =?UTF-8?q?entar=20e=20verifica=C3=A7=C3=A3o=20de=20imagem=20v=C3=A1lida.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- base/forms.py | 2 +- materia/models.py | 6 ++-- parlamentares/forms.py | 9 +++-- parlamentares/models.py | 5 +-- parlamentares/views.py | 64 +++++++++++++---------------------- requirements/requirements.txt | 1 + sapl/utils.py | 57 +++++++++++++++++++++++++++++++ 7 files changed, 96 insertions(+), 48 deletions(-) diff --git a/base/forms.py b/base/forms.py index 50161fb8c..f37f886ac 100644 --- a/base/forms.py +++ b/base/forms.py @@ -78,7 +78,7 @@ class CasaLegislativaTabelaAuxForm(ModelForm): row3, row4, row5, - HTML("""{% if form.logotipo.value %} + HTML("""{% if not form.fotografia.errors and form.fotografia.value %}

diff --git a/materia/models.py b/materia/models.py index 1d6f96d5c..a9e864931 100644 --- a/materia/models.py +++ b/materia/models.py @@ -4,7 +4,8 @@ from model_utils import Choices from comissoes.models import Comissao from parlamentares.models import Parlamentar, Partido -from sapl.utils import RANGE_ANOS, YES_NO_CHOICES, xstr +from sapl.utils import (restringe_tipos_de_arquivo_txt, + RANGE_ANOS, YES_NO_CHOICES, xstr) class TipoMateriaLegislativa(models.Model): @@ -457,7 +458,8 @@ class Proposicao(models.Model): blank=True, null=True, upload_to=texto_upload_path, - verbose_name=_('Texto Original (PDF)')) + verbose_name=_('Texto Original (PDF)'), + validators=[restringe_tipos_de_arquivo_txt]) class Meta: verbose_name = _('Proposição') diff --git a/parlamentares/forms.py b/parlamentares/forms.py index 9faa5df27..5d57d8f22 100644 --- a/parlamentares/forms.py +++ b/parlamentares/forms.py @@ -131,15 +131,18 @@ class ParlamentaresForm (ModelForm): row1, row2, row3, row4, row5, row6, row7, row8, row9, row10, row11, row12, row13, - HTML("""{% if form.fotografia.value %} + HTML(""" + {% if not form.fotografia.errors %} + {% if form.fotografia.value %}

+ {% endif %} {% endif %}""", ), row14, form_actions()) diff --git a/parlamentares/models.py b/parlamentares/models.py index a1055602d..6842ced10 100644 --- a/parlamentares/models.py +++ b/parlamentares/models.py @@ -4,7 +4,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from model_utils import Choices -from sapl.utils import UF, YES_NO_CHOICES +from sapl.utils import restringe_tipos_de_arquivo_img, UF, YES_NO_CHOICES class Legislatura(models.Model): @@ -241,7 +241,8 @@ class Parlamentar(models.Model): blank=True, null=True, upload_to=foto_upload_path, - verbose_name=_('Fotografia')) + verbose_name=_('Fotografia'), + validators=[restringe_tipos_de_arquivo_img]) class Meta: verbose_name = _('Parlamentar') diff --git a/parlamentares/views.py b/parlamentares/views.py index b6803f182..b22f95a31 100644 --- a/parlamentares/views.py +++ b/parlamentares/views.py @@ -1,9 +1,11 @@ import os +from braces.views import FormMessagesMixin from django.contrib import messages -from django.core.urlresolvers import reverse +from django.core.urlresolvers import reverse, reverse_lazy +from django.http import HttpResponseRedirect from django.utils.translation import ugettext_lazy as _ -from django.views.generic import FormView +from django.views.generic import CreateView, FormView, UpdateView from crud import Crud @@ -139,45 +141,27 @@ class ParlamentaresCadastroView(FormView): {'form': form, 'legislatura_id': pk}) -class ParlamentaresEditarView(FormView): +class ParlamentaresEditarView(UpdateView): template_name = "parlamentares/parlamentares_cadastro.html" - - def get_success_url(self): - return reverse('parlamentares') - - def get(self, request, *args, **kwargs): - pk = kwargs['pk'] - parlamentar = Parlamentar.objects.get(pk=pk) - form = ParlamentaresEditForm(instance=parlamentar) - return self.render_to_response( - {'form': form, 'object': parlamentar}) - - def post(self, request, *args, **kwargs): - pk = kwargs['pk'] - parlamentar = Parlamentar.objects.get(pk=pk) - form = ParlamentaresEditForm(request.POST, instance=parlamentar) - - if form.is_valid(): - if 'salvar' in request.POST: - parlamentar = form.save(commit=False) - if 'fotografia' in request.FILES: - parlamentar.fotografia = request.FILES['fotografia'] - parlamentar.biografia = form.data['biografia'] - parlamentar.save() - elif 'excluir' in request.POST: - Mandato.objects.get(parlamentar=parlamentar).delete() - parlamentar.delete() - elif "remover" in request.POST: - try: - os.unlink(parlamentar.fotografia.path) - except OSError: - pass # Should log this error!!!!! - parlamentar = form.save(commit=False) - parlamentar.fotografia = None - parlamentar.save() - return self.form_valid(form) - else: - return self.render_to_response({'form': form}) + form_class = ParlamentaresEditForm + model = Parlamentar + success_url = reverse_lazy('parlamentares') + + def form_valid(self, form): + parlamentar = form.instance + if 'salvar' in self.request.POST: + form.save() + elif 'excluir' in self.request.POST: + Mandato.objects.get(parlamentar=parlamentar).delete() + parlamentar.delete() + elif "remover-foto" in self.request.POST: + try: + os.unlink(parlamentar.fotografia.path) + except OSError: + pass # Should log this error!!!!! + parlamentar.fotografia = None + parlamentar.save() + return HttpResponseRedirect(self.get_success_url()) class ParlamentaresDependentesView(FormView): diff --git a/requirements/requirements.txt b/requirements/requirements.txt index fa666f49b..d799f0b35 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -17,3 +17,4 @@ pytz==2015.7 pyyaml==3.11 rtyaml==0.0.2 unipath==1.1 +python-magic==0.4.10 diff --git a/sapl/utils.py b/sapl/utils.py index f5707d197..83a3fc820 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -1,10 +1,13 @@ from datetime import date + from functools import wraps from django.apps import apps from django.contrib import admin +from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ +import magic autor_label = '''
@@ -119,3 +122,57 @@ UF = [ ] RANGE_ANOS = [(year, year) for year in range(date.today().year, 1889, -1)] + +TIPOS_TEXTO_PERMITIDOS = ( + 'application/vnd.oasis.opendocument.text', + 'application/x-vnd.oasis.opendocument.text', + 'application/pdf', + 'application/x-pdf', + 'application/acrobat', + 'applications/vnd.pdf', + 'text/pdf', + 'text/x-pdf', + 'text/plain', + 'application/txt', + 'browser/internal', + 'text/anytext', + 'widetext/plain', + 'widetext/paragraph', + 'application/msword', + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', +) + +TIPOS_IMG_PERMITIDOS = ( + 'image/jpeg', + 'image/jpg', + 'image/jpe_', + 'image/pjpeg', + 'image/vnd.swiftview-jpeg', + 'application/jpg', + 'application/x-jpg', + 'image/pjpeg', + 'image/pipeg', + 'image/vnd.swiftview-jpeg', + 'image/x-xbitmap', + 'image/bmp', + 'image/x-bmp', + 'image/x-bitmap', + 'image/png', + 'application/png', + 'application/x-png', +) + + +def fabrica_validador_de_tipos_de_arquivo(lista): + + def restringe_tipos_de_arquivo(value): + mime = magic.from_buffer(value.read(), mime=True) + mime = mime.decode() + if mime not in lista: + raise ValidationError(_('Tipo de arquivo não suportado')) + return restringe_tipos_de_arquivo + +restringe_tipos_de_arquivo_txt = fabrica_validador_de_tipos_de_arquivo( + TIPOS_TEXTO_PERMITIDOS) +restringe_tipos_de_arquivo_img = fabrica_validador_de_tipos_de_arquivo( + TIPOS_IMG_PERMITIDOS) From 8ce1150b29055647085366f747131bfd83d36dd9 Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Tue, 15 Mar 2016 18:38:56 -0300 Subject: [PATCH 04/27] Altera ParlamentaresEditView --- parlamentares/views.py | 59 +++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 38 deletions(-) diff --git a/parlamentares/views.py b/parlamentares/views.py index b34c5f507..a111558f1 100644 --- a/parlamentares/views.py +++ b/parlamentares/views.py @@ -3,7 +3,7 @@ import os from django.contrib import messages from django.core.urlresolvers import reverse from django.utils.translation import ugettext_lazy as _ -from django.views.generic import CreateView, FormView +from django.views.generic import FormView from crud import Crud @@ -139,44 +139,27 @@ class ParlamentaresCadastroView(FormView): {'form': form, 'legislatura_id': pk}) -class ParlamentaresEditarView(FormView): +class ParlamentaresEditarView(UpdateView): template_name = "parlamentares/parlamentares_cadastro.html" - form_class = ParlamentaresForm - - def get_success_url(self): - return reverse('parlamentares') - - def get(self, request, *args, **kwargs): - pk = kwargs['pk'] - parlamentar = Parlamentar.objects.get(pk=pk) - form = ParlamentaresEditForm(instance=parlamentar) - return self.render_to_response( - {'form': form, 'object': parlamentar}) - - def post(self, request, *args, **kwargs): - pk = kwargs['pk'] - parlamentar = Parlamentar.objects.get(pk=pk) - - form = ParlamentaresEditForm(request.POST, - request.FILES, - instance=parlamentar) - - if form.is_valid(): - if 'salvar' in request.POST: - form.save() - elif 'excluir' in request.POST: - Mandato.objects.get(parlamentar=parlamentar).delete() - parlamentar.delete() - elif "remover" in request.POST: - try: - os.unlink(parlamentar.fotografia.path) - except OSError: - pass # Should log this error!!!!! - parlamentar.fotografia = None - parlamentar.save() - return self.form_valid(form) - else: - return self.render_to_response({'form': form}) + form_class = ParlamentaresEditForm + model = Parlamentar + success_url = reverse_lazy('parlamentares') + + def form_valid(self, form): + parlamentar = form.instance + if 'salvar' in self.request.POST: + form.save() + elif 'excluir' in self.request.POST: + Mandato.objects.get(parlamentar=parlamentar).delete() + parlamentar.delete() + elif "remover-foto" in self.request.POST: + try: + os.unlink(parlamentar.fotografia.path) + except OSError: + pass # Should log this error!!!!! + parlamentar.fotografia = None + parlamentar.save() + return HttpResponseRedirect(self.get_success_url()) class ParlamentaresDependentesView(FormView): From ebe51873109ad981fb60e07b2a2f5e4c96e494ff Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Wed, 16 Mar 2016 10:57:48 -0300 Subject: [PATCH 05/27] Restringe tipos de texto original em proposicao, adiciona botao de remover texto original e adiciona novos mime types em restricao de textos --- materia/forms.py | 11 +++++++++++ materia/models.py | 5 +++-- materia/views.py | 12 +++++++++++- parlamentares/forms.py | 4 ---- sapl/utils.py | 5 ++++- 5 files changed, 29 insertions(+), 8 deletions(-) diff --git a/materia/forms.py b/materia/forms.py index 6b260d58e..24c81b4a6 100644 --- a/materia/forms.py +++ b/materia/forms.py @@ -61,6 +61,17 @@ class ProposicaoForm(ModelForm): self.helper.layout = Layout( Fieldset(_('Incluir Proposição'), row1, row2, row3, row4, + HTML(""" +
+

+ +

+ """, ), form_actions(more=more)) ) super(ProposicaoForm, self).__init__( diff --git a/materia/models.py b/materia/models.py index a9e864931..724c7f5ae 100644 --- a/materia/models.py +++ b/materia/models.py @@ -4,7 +4,7 @@ from model_utils import Choices from comissoes.models import Comissao from parlamentares.models import Parlamentar, Partido -from sapl.utils import (restringe_tipos_de_arquivo_txt, +from sapl.utils import (restringe_tipos_de_arquivo_txt, RANGE_ANOS, YES_NO_CHOICES, xstr) @@ -123,7 +123,8 @@ class MateriaLegislativa(models.Model): blank=True, null=True, upload_to=texto_upload_path, - verbose_name=_('Texto Original (PDF)')) + verbose_name=_('Texto Original (PDF)'), + validators=[restringe_tipos_de_arquivo_txt]) class Meta: verbose_name = _('Matéria Legislativa') diff --git a/materia/views.py b/materia/views.py index 078228495..b7251edb6 100644 --- a/materia/views.py +++ b/materia/views.py @@ -1,3 +1,5 @@ +import os + from datetime import datetime from random import choice from string import ascii_letters, digits @@ -1377,8 +1379,10 @@ class ProposicaoEditView(CreateView): proposicao.save() else: proposicao.delete() - elif 'salvar' in request.POST: + if 'salvar' or "remover-foto" in request.POST: if 'texto_original' in request.FILES: + # if os.unlink(proposicao.texto_original.path): + # proposicao.texto_original = None proposicao.texto_original = request.FILES['texto_original'] tipo = TipoProposicao.objects.get(id=form.data['tipo']) proposicao.tipo = tipo @@ -1397,6 +1401,12 @@ class ProposicaoEditView(CreateView): proposicao.autor = materia.autoria_set.first().autor proposicao.materia = materia proposicao.data_envio = datetime.now() + if "remover-texto" in request.POST: + try: + os.unlink(proposicao.texto_original.path) + except OSError: + pass # Should log this error!!!!! + proposicao.texto_original = None proposicao.save() return redirect(self.get_success_url()) else: diff --git a/parlamentares/forms.py b/parlamentares/forms.py index 64c8daff2..5d57d8f22 100644 --- a/parlamentares/forms.py +++ b/parlamentares/forms.py @@ -142,11 +142,7 @@ class ParlamentaresForm (ModelForm): id="remover-foto" class="btn btn-warning" value="Remover Foto"/> -<<<<<<< HEAD - {% endif %} -======= {% endif %} ->>>>>>> 490fffbf4e0e50be52d47056821e7f626ce76dcd {% endif %}""", ), row14, form_actions()) diff --git a/sapl/utils.py b/sapl/utils.py index 83a3fc820..e06092ea9 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -140,7 +140,10 @@ TIPOS_TEXTO_PERMITIDOS = ( 'widetext/paragraph', 'application/msword', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', -) + 'application/xml', + 'text/xml', + 'text/html', + ) TIPOS_IMG_PERMITIDOS = ( 'image/jpeg', From a527605626126a5208c8aadc9ed042c729606780 Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Wed, 16 Mar 2016 11:47:29 -0300 Subject: [PATCH 06/27] Faz o merge com o master --- base/forms.py | 10 ++ base/urls.py | 3 +- comissoes/urls.py | 20 +-- comissoes/views.py | 18 +-- compilacao/urls.py | 12 +- compilacao/views.py | 15 +-- {crud_tests => crud}/__init__.py | 0 crud.py => crud/base.py | 124 +++++++++--------- crud/tests/__init__.py | 0 {crud_tests => crud/tests}/settings.py | 15 +-- .../tests/stub_app}/layouts.yaml | 0 {crud_tests => crud/tests/stub_app}/models.py | 0 .../tests/stub_app}/templates/base.html | 0 crud/tests/stub_app/urls.py | 7 + crud/tests/stub_app/views.py | 11 ++ .../test_flux.py => crud/tests/test_base.py | 12 +- crud_tests/urls.py | 7 - crud_tests/views.py | 13 -- lexml/urls.py | 8 +- lexml/views.py | 6 +- materia/forms.py | 19 +++ materia/urls.py | 62 ++++----- materia/views.py | 43 +++--- norma/forms.py | 20 ++- norma/urls.py | 30 +++-- norma/views.py | 34 ++--- painel/urls.py | 4 +- painel/views.py | 4 +- parlamentares/urls.py | 35 ++--- parlamentares/views.py | 28 ++-- protocoloadm/forms.py | 6 +- protocoloadm/urls.py | 37 +++--- protocoloadm/views.py | 19 +-- pytest.ini | 2 +- relatorios/views.py | 1 + sessao/forms.py | 19 +++ sessao/urls.py | 28 ++-- sessao/views.py | 74 +++++------ test_and_check_qa.sh | 2 +- 39 files changed, 410 insertions(+), 338 deletions(-) rename {crud_tests => crud}/__init__.py (100%) rename crud.py => crud/base.py (63%) create mode 100644 crud/tests/__init__.py rename {crud_tests => crud/tests}/settings.py (85%) rename {crud_tests => crud/tests/stub_app}/layouts.yaml (100%) rename {crud_tests => crud/tests/stub_app}/models.py (100%) rename {crud_tests => crud/tests/stub_app}/templates/base.html (100%) create mode 100644 crud/tests/stub_app/urls.py create mode 100644 crud/tests/stub_app/views.py rename crud_tests/test_flux.py => crud/tests/test_base.py (97%) delete mode 100644 crud_tests/urls.py delete mode 100644 crud_tests/views.py diff --git a/base/forms.py b/base/forms.py index f37f886ac..385812338 100644 --- a/base/forms.py +++ b/base/forms.py @@ -1,6 +1,7 @@ from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Fieldset, Layout from django import forms +from django.core.exceptions import ValidationError from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ @@ -38,6 +39,15 @@ class CasaLegislativaTabelaAuxForm(ModelForm): attrs={'id': 'casa-informacoes'}) } + def clean_logotipo(self): + logotipo = self.cleaned_data.get('logotipo', False) + if logotipo: + if logotipo.size > 2*1024*1024: + raise ValidationError("Imagem muito grande. ( > 2mb )") + return logotipo + else: + raise ValidationError("Não foi possível salvar a imagem.") + def __init__(self, *args, **kwargs): row1 = crispy_layout_mixin.to_row( diff --git a/base/urls.py b/base/urls.py index e77cd643d..f7806f843 100644 --- a/base/urls.py +++ b/base/urls.py @@ -1,7 +1,6 @@ from django.conf.urls import url -from django.views.generic.base import TemplateView - from django.contrib.staticfiles.urls import staticfiles_urlpatterns +from django.views.generic.base import TemplateView from .views import CasaLegislativaTableAuxView, HelpView diff --git a/comissoes/urls.py b/comissoes/urls.py index 4415c0283..dfbde7d40 100644 --- a/comissoes/urls.py +++ b/comissoes/urls.py @@ -1,13 +1,15 @@ from django.conf.urls import include, url -from comissoes.views import (CadastrarComissaoView, +from comissoes.views import (CadastrarComissaoView, CargoCrud, ComissaoCrud, ComissaoParlamentarEditView, ComissaoParlamentarIncluirView, ComposicaoView, MateriasTramitacaoListView, MateriasView, - ReunioesView, cargo_crud, comissao_crud, - periodo_composicao_crud, tipo_comissao_crud) + PeriodoComposicaoCrud, ReunioesView, + TipoComissaoCrud) -comissao_url_patterns = comissao_crud.urlpatterns + [ +comissao_url_patterns, namespace = ComissaoCrud.get_urls() + +comissao_url_patterns = comissao_url_patterns + [ url(r'^(?P\d+)/composicao$', ComposicaoView.as_view(), name='composicao'), url(r'^(?P\d+)/materias-em-tramitacao$', @@ -27,12 +29,10 @@ comissao_url_patterns = comissao_crud.urlpatterns + [ ] urlpatterns = [ - url(r'^comissoes/', include(comissao_url_patterns, - comissao_crud.namespace, - comissao_crud.namespace)), + url(r'^comissoes/', include(comissao_url_patterns, namespace)), - url(r'^sistema/comissoes/cargo/', include(cargo_crud.urls)), + url(r'^sistema/comissoes/cargo/', include(CargoCrud.get_urls())), url(r'^sistema/comissoes/periodo-composicao/', - include(periodo_composicao_crud.urls)), - url(r'^sistema/comissoes/tipo/', include(tipo_comissao_crud.urls)), + include(PeriodoComposicaoCrud.get_urls())), + url(r'^sistema/comissoes/tipo/', include(TipoComissaoCrud.get_urls())), ] diff --git a/comissoes/views.py b/comissoes/views.py index 11e6d7ac6..0dd5a4812 100644 --- a/comissoes/views.py +++ b/comissoes/views.py @@ -3,7 +3,7 @@ from django.core.urlresolvers import reverse, reverse_lazy from django.utils.translation import ugettext_lazy as _ from django.views.generic import CreateView, FormView, ListView -from crud import Crud +from crud.base import Crud from materia.models import Tramitacao from parlamentares.models import Filiacao @@ -12,10 +12,10 @@ from .forms import (CadastrarComissaoForm, ComposicaoForm, from .models import (CargoComissao, Comissao, Composicao, Participacao, Periodo, TipoComissao) -cargo_crud = Crud(CargoComissao, 'cargo_comissao') -periodo_composicao_crud = Crud(Periodo, 'periodo_composicao_comissao') -tipo_comissao_crud = Crud(TipoComissao, 'tipo_comissao') -comissao_crud = Crud(Comissao, 'modulo_comissoes') +CargoCrud = Crud.build(CargoComissao, 'cargo_comissao') +PeriodoComposicaoCrud = Crud.build(Periodo, 'periodo_composicao_comissao') +TipoComissaoCrud = Crud.build(TipoComissao, 'tipo_comissao') +ComissaoCrud = Crud.build(Comissao, 'modulo_comissoes') class CadastrarComissaoView(CreateView): @@ -66,11 +66,11 @@ class ComposicaoView(FormView): 'object': Comissao.objects.get(id=self.kwargs['pk'])}) -class MateriasView(comissao_crud.CrudDetailView): +class MateriasView(ComissaoCrud.CrudDetailView): template_name = 'comissoes/materias.html' -class ReunioesView(comissao_crud.CrudDetailView): +class ReunioesView(ComissaoCrud.CrudDetailView): template_name = 'comissoes/reunioes.html' @@ -135,7 +135,7 @@ class ComissaoParlamentarEditView(FormView): participacao = Participacao.objects.get(id=participacao_id) comissao = Comissao.objects.get(id=self.kwargs['pk']) id_parlamentar = Filiacao.objects.filter( - parlamentar__id=participacao.parlamentar.id).order_by('data') + parlamentar__id=participacao.parlamentar.id).order_by('data') id_parlamentar = id_parlamentar.last().id form = ParticipacaoCadastroForm( initial={'parlamentar_id': id_parlamentar}, @@ -151,7 +151,7 @@ class ComissaoParlamentarEditView(FormView): request.POST, request.FILES, instance=Participacao.objects.get(id=kwargs['id']) - ).save(commit=False) + ).save(commit=False) participacao.composicao = Composicao.objects.get( id=kwargs['cd']) diff --git a/compilacao/urls.py b/compilacao/urls.py index b90eb215b..e11fad89c 100644 --- a/compilacao/urls.py +++ b/compilacao/urls.py @@ -1,8 +1,8 @@ from django.conf.urls import include, url from compilacao import views -from compilacao.views import (tipo_nota_crud, tipo_publicacao_crud, - tipo_vide_crud, veiculo_publicacao_crud) +from compilacao.views import (TipoNotaCrud, TipoPublicacaoCrud, TipoVideCrud, + VeiculoPublicacaoCrud) urlpatterns_compilacao = [ url(r'^$', views.TaListView.as_view(), name='ta_list'), @@ -93,12 +93,12 @@ urlpatterns = [ url(r'^ta/', include(urlpatterns_compilacao, 'compilacao', 'compilacao')), url(r'^ta/config/tipo-nota/', - include(tipo_nota_crud.urls)), + include(TipoNotaCrud.get_urls())), url(r'^ta/config/tipo-vide/', - include(tipo_vide_crud.urls)), + include(TipoVideCrud.get_urls())), url(r'^ta/config/tipo-publicacao/', - include(tipo_publicacao_crud.urls)), + include(TipoPublicacaoCrud.get_urls())), url(r'^ta/config/veiculo-publicacao/', - include(veiculo_publicacao_crud.urls)), + include(VeiculoPublicacaoCrud.get_urls())), ] diff --git a/compilacao/views.py b/compilacao/views.py index c705a36e0..a331705f1 100644 --- a/compilacao/views.py +++ b/compilacao/views.py @@ -27,7 +27,7 @@ from compilacao.models import (Dispositivo, Nota, TextoArticulado, TipoDispositivo, TipoNota, TipoPublicacao, TipoTextoArticulado, TipoVide, VeiculoPublicacao, Vide) -from crud import Crud, CrudListMixin, make_pagination +from crud.base import Crud, CrudListView, make_pagination DISPOSITIVO_SELECT_RELATED = ( 'tipo_dispositivo', @@ -42,13 +42,10 @@ DISPOSITIVO_SELECT_RELATED = ( 'ta_publicado', 'ta',) -tipo_nota_crud = Crud(TipoNota, 'tipo_nota') -tipo_vide_crud = Crud(TipoVide, 'tipo_vide') -tipo_publicacao_crud = Crud(TipoPublicacao, 'tipo_publicacao') -veiculo_publicacao_crud = Crud(VeiculoPublicacao, 'veiculo_publicacao') -perfil_estr_txt_norm = Crud(PerfilEstruturalTextoArticulado, - 'perfil_estrutural') -tipo_dispositivo_crud = Crud(TipoDispositivo, 'tipo_dispositivo') +TipoNotaCrud = Crud.build(TipoNota, 'tipo_nota') +TipoVideCrud = Crud.build(TipoVide, 'tipo_vide') +TipoPublicacaoCrud = Crud.build(TipoPublicacao, 'tipo_publicacao') +VeiculoPublicacaoCrud = Crud.build(VeiculoPublicacao, 'veiculo_publicacao') class IntegracaoTaView(TemplateView): @@ -1667,7 +1664,7 @@ class PublicacaoListView(ListView): def get_context_data(self, **kwargs): context = super(PublicacaoListView, self).get_context_data(**kwargs) - context['NO_ENTRIES_MSG'] = CrudListMixin.no_entries_msg + context['NO_ENTRIES_MSG'] = CrudListView.no_entries_msg return context diff --git a/crud_tests/__init__.py b/crud/__init__.py similarity index 100% rename from crud_tests/__init__.py rename to crud/__init__.py diff --git a/crud.py b/crud/base.py similarity index 63% rename from crud.py rename to crud/base.py index 646c19d77..0010209ee 100644 --- a/crud.py +++ b/crud/base.py @@ -1,6 +1,7 @@ from braces.views import FormMessagesMixin from django.conf.urls import url from django.core.urlresolvers import reverse +from django.utils.decorators import classonlymethod from django.utils.translation import ugettext_lazy as _ from django.views.generic import (CreateView, DeleteView, DetailView, ListView, UpdateView) @@ -8,6 +9,19 @@ from django.views.generic import (CreateView, DeleteView, DetailView, ListView, from crispy_layout_mixin import CrispyLayoutFormMixin, get_field_display +def _form_invalid_message(msg): + return '%s %s' % (_('Formulário inválido.'), msg) + +FORM_MESSAGES = {'create': (_('Registro criado com sucesso!'), + _('O registro não foi criado.')), + 'update': (_('Registro alterado com sucesso!'), + _('Suas alterações não foram salvas.')), + 'delete': (_('Registro excluído com sucesso!'), + _('O registro não foi excluído.'))} +FORM_MESSAGES = {k: (a, _form_invalid_message(b)) + for k, (a, b) in FORM_MESSAGES.items()} + + def from_to(start, end): return list(range(start, end + 1)) @@ -39,7 +53,7 @@ def make_pagination(index, num_pages): return head + [None] + tail -class BaseCrudMixin(CrispyLayoutFormMixin): +class BaseMixin(CrispyLayoutFormMixin): @property def namespace(self): @@ -69,7 +83,7 @@ class BaseCrudMixin(CrispyLayoutFormMixin): return self.resolve_url('delete', args=(self.object.id,)) def get_template_names(self): - names = super(BaseCrudMixin, self).get_template_names() + names = super(BaseMixin, self).get_template_names() names.append("crud/%s.html" % self.template_name_suffix.lstrip('_')) return names @@ -83,7 +97,7 @@ class BaseCrudMixin(CrispyLayoutFormMixin): return self.model._meta.verbose_name_plural -class CrudListMixin(): +class CrudListView(ListView): paginate_by = 10 no_entries_msg = _('Nenhum registro encontrado.') @@ -94,7 +108,7 @@ class CrudListMixin(): for i, name in enumerate(self.list_field_names)] def get_context_data(self, **kwargs): - context = super(CrudListMixin, self).get_context_data(**kwargs) + context = super(CrudListView, self).get_context_data(**kwargs) context.setdefault('title', self.verbose_name_plural) # pagination @@ -115,15 +129,9 @@ class CrudListMixin(): return context -def make_form_invalid_message(msg): - return '%s %s' % (_('Formulário inválido.'), msg) - - -class CrudCreateMixin(FormMessagesMixin): +class CrudCreateView(FormMessagesMixin, CreateView): - form_valid_message = _('Registro criado com sucesso!') - form_invalid_message = make_form_invalid_message( - _('O registro não foi criado.')) + form_valid_message, form_invalid_message = FORM_MESSAGES['create'] @property def cancel_url(self): @@ -135,18 +143,12 @@ class CrudCreateMixin(FormMessagesMixin): def get_context_data(self, **kwargs): kwargs.setdefault('title', _('Adicionar %(verbose_name)s') % { 'verbose_name': self.verbose_name}) - return super(CrudCreateMixin, self).get_context_data(**kwargs) - + return super(CrudCreateView, self).get_context_data(**kwargs) -class CrudDetailMixin(): - pass +class CrudUpdateView(FormMessagesMixin, UpdateView): -class CrudUpdateMixin(FormMessagesMixin): - - form_valid_message = _('Registro alterado com sucesso!') - form_invalid_message = make_form_invalid_message( - _('Suas alterações não foram salvas.')) + form_valid_message, form_invalid_message = FORM_MESSAGES['update'] @property def cancel_url(self): @@ -156,11 +158,9 @@ class CrudUpdateMixin(FormMessagesMixin): return self.detail_url -class CrudDeleteMixin(FormMessagesMixin): +class CrudDeleteView(FormMessagesMixin, DeleteView): - form_valid_message = _('Registro excluído com sucesso!') - form_invalid_message = make_form_invalid_message( - _('O registro não foi excluído.')) + form_valid_message, form_invalid_message = FORM_MESSAGES['delete'] @property def cancel_url(self): @@ -171,36 +171,31 @@ class CrudDeleteMixin(FormMessagesMixin): class Crud: - - def __init__(self, model, help_path, - base_mixin=BaseCrudMixin, - list_mixin=CrudListMixin, - create_mixin=CrudCreateMixin, - detail_mixin=CrudDetailMixin, - update_mixin=CrudUpdateMixin, - delete_mixin=CrudDeleteMixin): - - class CrudMixin(base_mixin): - pass - CrudMixin.model = model - CrudMixin.help_path = help_path - - class CrudListView(CrudMixin, list_mixin, ListView): - pass - - class CrudCreateView(CrudMixin, create_mixin, CreateView): - pass - - class CrudDetailView(CrudMixin, detail_mixin, DetailView): - pass - - class CrudUpdateView(CrudMixin, update_mixin, UpdateView): - pass - - class CrudDeleteView(CrudMixin, delete_mixin, DeleteView): - pass - - self.urlpatterns = [ + BaseMixin = BaseMixin + ListView = CrudListView + CreateView = CrudCreateView + DetailView = DetailView + UpdateView = CrudUpdateView + DeleteView = CrudDeleteView + help_path = '' + + @classonlymethod + def get_urls(cls): + + def _add_base(view): + class CrudViewWithBase(cls.BaseMixin, view): + model = cls.model + help_path = cls.help_path + CrudViewWithBase.__name__ = view.__name__ + return CrudViewWithBase + + CrudListView = _add_base(cls.ListView) + CrudCreateView = _add_base(cls.CreateView) + CrudDetailView = _add_base(cls.DetailView) + CrudUpdateView = _add_base(cls.UpdateView) + CrudDeleteView = _add_base(cls.DeleteView) + + urlpatterns = [ url(r'^$', CrudListView.as_view(), name='list'), url(r'^create$', CrudCreateView.as_view(), name='create'), url(r'^(?P\d+)$', CrudDetailView.as_view(), name='detail'), @@ -210,8 +205,19 @@ class Crud: CrudDeleteView.as_view(), name='delete'), ] - self.namespace = CrudMixin().namespace - self.urls = self.urlpatterns, self.namespace, self.namespace + return urlpatterns, _add_base(object)().namespace + + @classonlymethod + def build(cls, _model, _help_path): + class ModelCrud(cls): + model = _model + help_path = _help_path + + # FIXME!!!! corrigir referencias no codigo e remover isso!!!!! + # fazer com #230 + class CrudDetailView(cls.BaseMixin, cls.DetailView): + model = _model + help_path = _help_path - # FIXME Refatorar código que precisa desse atributo e remover - self.CrudDetailView = CrudDetailView + ModelCrud.__name__ = '%sCrud' % _model.__name__ + return ModelCrud diff --git a/crud/tests/__init__.py b/crud/tests/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/crud_tests/settings.py b/crud/tests/settings.py similarity index 85% rename from crud_tests/settings.py rename to crud/tests/settings.py index 5393f0bb3..d2450045a 100644 --- a/crud_tests/settings.py +++ b/crud/tests/settings.py @@ -1,12 +1,11 @@ -import os +from os.path import dirname, join -BASE_DIR = os.path.dirname(os.path.dirname(__file__)) +BASE_DIR = dirname(dirname(dirname(__file__))) DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', - # 'NAME': ':memory:', - 'NAME': '/tmp/db', + 'NAME': ':memory:', }, } @@ -15,11 +14,11 @@ INSTALLED_APPS = ( 'django.contrib.auth', 'django.contrib.messages', 'django.contrib.sessions', - 'crud_tests', + 'crud.tests.stub_app', 'crispy_forms', ) -ROOT_URLCONF = 'crud_tests.urls' +ROOT_URLCONF = 'crud.tests.stub_app.urls' USE_TZ = True @@ -27,8 +26,8 @@ SECRET_KEY = 'zzz...' TEMPLATES = [{ 'BACKEND': 'django.template.backends.django.DjangoTemplates', - 'DIRS': [os.path.join(BASE_DIR, 'crud_tests/templates'), - os.path.join(BASE_DIR, 'templates')], + 'DIRS': [join(BASE_DIR, 'crud/tests/stub_app/templates'), + join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ diff --git a/crud_tests/layouts.yaml b/crud/tests/stub_app/layouts.yaml similarity index 100% rename from crud_tests/layouts.yaml rename to crud/tests/stub_app/layouts.yaml diff --git a/crud_tests/models.py b/crud/tests/stub_app/models.py similarity index 100% rename from crud_tests/models.py rename to crud/tests/stub_app/models.py diff --git a/crud_tests/templates/base.html b/crud/tests/stub_app/templates/base.html similarity index 100% rename from crud_tests/templates/base.html rename to crud/tests/stub_app/templates/base.html diff --git a/crud/tests/stub_app/urls.py b/crud/tests/stub_app/urls.py new file mode 100644 index 000000000..3224f5c1a --- /dev/null +++ b/crud/tests/stub_app/urls.py @@ -0,0 +1,7 @@ +from django.conf.urls import include, url + +from .views import CountryCrud + +urlpatterns = [ + url(r'^countries/', include(CountryCrud.get_urls())), +] diff --git a/crud/tests/stub_app/views.py b/crud/tests/stub_app/views.py new file mode 100644 index 000000000..315397696 --- /dev/null +++ b/crud/tests/stub_app/views.py @@ -0,0 +1,11 @@ +from crud.base import Crud, CrudListView + +from .models import Country + + +class CountryCrud(Crud): + model = Country + help_path = 'help_path', + + class ListView(CrudListView): + paginate_by = 10 diff --git a/crud_tests/test_flux.py b/crud/tests/test_base.py similarity index 97% rename from crud_tests/test_flux.py rename to crud/tests/test_base.py index f60b2e6a0..b8a94a4c9 100644 --- a/crud_tests/test_flux.py +++ b/crud/tests/test_base.py @@ -2,11 +2,11 @@ import pytest from django.core.urlresolvers import reverse from model_mommy import mommy -from crud import (CrispyLayoutFormMixin, CrudListMixin, from_to, - get_field_display, make_pagination) +from crud.base import (CrispyLayoutFormMixin, CrudListView, from_to, + get_field_display, make_pagination) -from .models import Continent, Country -from .views import CountryCrudListMixin +from .stub_app.models import Continent, Country +from .stub_app.views import CountryCrud pytestmark = pytest.mark.django_db @@ -151,7 +151,7 @@ def assert_h1(res, title): assert res.html.find('main').find('h1').text.strip() == title -NO_ENTRIES_MSG = str(CrudListMixin.no_entries_msg) # "unlazy" +NO_ENTRIES_MSG = str(CrudListView.no_entries_msg) # "unlazy" def assert_on_list_page(res): @@ -196,7 +196,7 @@ def test_flux_list_paginate_detail( population=population, is_cold=is_cold) - CountryCrudListMixin.paginate_by = page_size + CountryCrud.ListView.paginate_by = page_size res = app.get('/countries/') diff --git a/crud_tests/urls.py b/crud_tests/urls.py deleted file mode 100644 index 94880e39e..000000000 --- a/crud_tests/urls.py +++ /dev/null @@ -1,7 +0,0 @@ -from django.conf.urls import include, url - -from .views import country_crud - -urlpatterns = [ - url(r'^countries/', include(country_crud.urls)), -] diff --git a/crud_tests/views.py b/crud_tests/views.py deleted file mode 100644 index 7c699dc45..000000000 --- a/crud_tests/views.py +++ /dev/null @@ -1,13 +0,0 @@ -from crud import Crud, CrudListMixin - -from .models import Country - - -class CountryCrudListMixin(CrudListMixin): - paginate_by = 10 - - -country_crud = Crud( - Country, - 'help_path', - list_mixin=CountryCrudListMixin) diff --git a/lexml/urls.py b/lexml/urls.py index f47ab9bdd..43935a8b1 100644 --- a/lexml/urls.py +++ b/lexml/urls.py @@ -1,8 +1,10 @@ from django.conf.urls import include, url -from lexml.views import lexml_provedor_crud, lexml_publicador_crud +from lexml.views import LexmlProvedorCrud, LexmlPublicadorCrud urlpatterns = [ - url(r'^sistema/lexml/provedor/', include(lexml_provedor_crud.urls)), - url(r'^sistema/lexml/publicador/', include(lexml_publicador_crud.urls)), + url(r'^sistema/lexml/provedor/', + include(LexmlProvedorCrud.get_urls())), + url(r'^sistema/lexml/publicador/', + include(LexmlPublicadorCrud.get_urls())), ] diff --git a/lexml/views.py b/lexml/views.py index d6957d1ef..249d57aa3 100644 --- a/lexml/views.py +++ b/lexml/views.py @@ -1,6 +1,6 @@ -from crud import Crud +from crud.base import Crud from .models import LexmlProvedor, LexmlPublicador -lexml_provedor_crud = Crud(LexmlProvedor, 'lexml_provedor') -lexml_publicador_crud = Crud(LexmlPublicador, 'lexml_publicador') +LexmlProvedorCrud = Crud.build(LexmlProvedor, 'lexml_provedor') +LexmlPublicadorCrud = Crud.build(LexmlPublicador, 'lexml_publicador') diff --git a/materia/forms.py b/materia/forms.py index 24c81b4a6..3de2c9d14 100644 --- a/materia/forms.py +++ b/materia/forms.py @@ -1,6 +1,7 @@ from crispy_forms.helper import FormHelper from crispy_forms.layout import HTML, Button, Column, Fieldset, Layout, Submit from django import forms +from django.core.exceptions import ValidationError from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ @@ -39,6 +40,15 @@ class ProposicaoForm(ModelForm): ano_materia = forms.CharField( label='Ano', required=False) + def clean_texto_original(self): + texto_original = self.cleaned_data.get('texto_original', False) + if texto_original: + if texto_original.size > 5*1024*1024: + raise ValidationError("Arquivo muito grande. ( > 5mb )") + return texto_original + else: + raise ValidationError("Não foi possível salvar o arquivo.") + class Meta: model = Proposicao fields = ['tipo', 'data_envio', 'descricao', 'texto_original'] @@ -409,6 +419,15 @@ class FormularioSimplificadoForm(ModelForm): 'data_apresentacao': forms.DateInput(attrs={'class': 'dateinput'}), } + def clean_texto_original(self): + texto_original = self.cleaned_data.get('texto_original', False) + if texto_original: + if texto_original.size > 5*1024*1024: + raise ValidationError("Arquivo muito grande. ( > 5mb )") + return texto_original + else: + raise ValidationError("Não foi possível salvar o arquivo.") + def __init__(self, *args, **kwargs): row1 = crispy_layout_mixin.to_row( diff --git a/materia/urls.py b/materia/urls.py index b37da3a43..69b5c08a7 100644 --- a/materia/urls.py +++ b/materia/urls.py @@ -2,32 +2,31 @@ from django.conf.urls import include, url from materia.views import (AcompanhamentoConfirmarView, AcompanhamentoExcluirView, - AcompanhamentoMateriaView, AutoriaEditView, - AutoriaView, DespachoInicialEditView, - DespachoInicialView, DocumentoAcessorioEditView, - DocumentoAcessorioView, FormularioCadastroView, - FormularioSimplificadoView, + AcompanhamentoMateriaView, AutorCrud, + AutoriaEditView, AutoriaView, + DespachoInicialEditView, DespachoInicialView, + DocumentoAcessorioEditView, DocumentoAcessorioView, + FormularioCadastroView, FormularioSimplificadoView, LegislacaoCitadaEditView, LegislacaoCitadaView, MateriaAnexadaEditView, MateriaAnexadaView, + MateriaLegislativaCrud, MateriaLegislativaPesquisaView, MateriaTaView, - NumeracaoEditView, NumeracaoView, - PesquisaMateriaListView, ProposicaoEditView, - ProposicaoListView, ProposicaoTaView, - ProposicaoView, RelatoriaEditView, RelatoriaView, - TramitacaoEditView, TramitacaoView, autor_crud, - materia_legislativa_crud, orgao_crud, origem_crud, - regime_tramitacao_crud, status_tramitacao_crud, - tipo_autor_crud, tipo_documento_crud, - tipo_fim_relatoria_crud, tipo_materia_crud, - tipo_proposicao_crud, unidade_tramitacao_crud) + NumeracaoEditView, NumeracaoView, OrgaoCrud, + OrigemCrud, PesquisaMateriaListView, + ProposicaoEditView, ProposicaoListView, + ProposicaoTaView, ProposicaoView, + RegimeTramitacaoCrud, RelatoriaEditView, + RelatoriaView, StatusTramitacaoCrud, TipoAutorCrud, + TipoDocumentoCrud, TipoFimRelatoriaCrud, + TipoMateriaCrud, TipoProposicaoCrud, + TramitacaoEditView, TramitacaoView, + UnidadeTramitacaoCrud) -materia_legislativa_patterns = materia_legislativa_crud.urlpatterns +materia_legislativa_patterns, namespace = MateriaLegislativaCrud.get_urls() urlpatterns = [ - url(r'^materia/', include(materia_legislativa_patterns, - materia_legislativa_crud.namespace, - materia_legislativa_crud.namespace)), + url(r'^materia/', include(materia_legislativa_patterns, namespace)), url(r'^materia/(?P[0-9]+)/ta$', @@ -36,23 +35,24 @@ urlpatterns = [ ProposicaoTaView.as_view(), name='proposicao_ta'), - url(r'^sistema/proposicoes/tipo/', include(tipo_proposicao_crud.urls)), - url(r'^sistema/proposicoes/autor/', include(autor_crud.urls)), - url(r'^sistema/materia/tipo/', include(tipo_materia_crud.urls)), + url(r'^sistema/proposicoes/tipo/', + include(TipoProposicaoCrud.get_urls())), + url(r'^sistema/proposicoes/autor/', include(AutorCrud.get_urls())), + url(r'^sistema/materia/tipo/', include(TipoMateriaCrud.get_urls())), url(r'^sistema/materia/regime-tramitacao/', - include(regime_tramitacao_crud.urls)), - url(r'^sistema/materia/tipo-autor/', include(tipo_autor_crud.urls)), + include(RegimeTramitacaoCrud.get_urls())), + url(r'^sistema/materia/tipo-autor/', include(TipoAutorCrud.get_urls())), url(r'^sistema/materia/tipo-documento/', - include(tipo_documento_crud.urls)), + include(TipoDocumentoCrud.get_urls())), url(r'^sistema/materia/tipo-fim-relatoria/', - include(tipo_fim_relatoria_crud.urls)), + include(TipoFimRelatoriaCrud.get_urls())), url(r'^sistema/materia/unidade-tramitacao/', - include(unidade_tramitacao_crud.urls)), - url(r'^sistema/materia/origem/', include(origem_crud.urls)), - url(r'^sistema/materia/autor/', include(autor_crud.urls)), + include(UnidadeTramitacaoCrud.get_urls())), + url(r'^sistema/materia/origem/', include(OrigemCrud.get_urls())), + url(r'^sistema/materia/autor/', include(AutorCrud.get_urls())), url(r'^sistema/materia/status-tramitacao/', - include(status_tramitacao_crud.urls)), - url(r'^sistema/materia/orgao/', include(orgao_crud.urls)), + include(StatusTramitacaoCrud.get_urls())), + url(r'^sistema/materia/orgao/', include(OrgaoCrud.get_urls())), url(r'^materia/formulario-simplificado', FormularioSimplificadoView.as_view(), name='formulario_simplificado'), diff --git a/materia/views.py b/materia/views.py index b7251edb6..d71e8908d 100644 --- a/materia/views.py +++ b/materia/views.py @@ -17,7 +17,7 @@ from django.views.generic import CreateView, FormView, ListView, TemplateView from base.models import CasaLegislativa from comissoes.models import Comissao, Composicao from compilacao.views import IntegracaoTaView -from crud import Crud, make_pagination +from crud.base import Crud, make_pagination from norma.models import LegislacaoCitada, NormaJuridica, TipoNormaJuridica from parlamentares.models import Partido from sapl.utils import get_base_url @@ -35,25 +35,26 @@ from .models import (AcompanhamentoMateria, Anexada, Autor, Autoria, TipoFimRelatoria, TipoMateriaLegislativa, TipoProposicao, Tramitacao, UnidadeTramitacao) -origem_crud = Crud(Origem, 'origem') -tipo_materia_crud = Crud(TipoMateriaLegislativa, 'tipo_materia_legislativa') -regime_tramitacao_crud = Crud(RegimeTramitacao, 'regime_tramitacao') -tipo_documento_crud = Crud(TipoDocumento, 'tipo_documento') -tipo_fim_relatoria_crud = Crud(TipoFimRelatoria, 'fim_relatoria') -materia_legislativa_crud = Crud(MateriaLegislativa, '') -Anexada_crud = Crud(Anexada, '') -tipo_autor_crud = Crud(TipoAutor, 'tipo_autor') -autor_crud = Crud(Autor, 'autor') -autoria_crud = Crud(Autoria, '') -documento_acessorio_crud = Crud(DocumentoAcessorio, '') -numeracao_crud = Crud(Numeracao, '') -orgao_crud = Crud(Orgao, 'orgao') -relatoria_crud = Crud(Relatoria, '') -tipo_proposicao_crud = Crud(TipoProposicao, 'tipo_proposicao') -proposicao_crud = Crud(Proposicao, '') -status_tramitacao_crud = Crud(StatusTramitacao, 'status_tramitacao') -unidade_tramitacao_crud = Crud(UnidadeTramitacao, 'unidade_tramitacao') -tramitacao_crud = Crud(Tramitacao, '') +OrigemCrud = Crud.build(Origem, 'origem') +TipoMateriaCrud = Crud.build(TipoMateriaLegislativa, + 'tipo_materia_legislativa') +RegimeTramitacaoCrud = Crud.build(RegimeTramitacao, 'regime_tramitacao') +TipoDocumentoCrud = Crud.build(TipoDocumento, 'tipo_documento') +TipoFimRelatoriaCrud = Crud.build(TipoFimRelatoria, 'fim_relatoria') +MateriaLegislativaCrud = Crud.build(MateriaLegislativa, '') +AnexadaCrud = Crud.build(Anexada, '') +TipoAutorCrud = Crud.build(TipoAutor, 'tipo_autor') +AutorCrud = Crud.build(Autor, 'autor') +AutoriaCrud = Crud.build(Autoria, '') +DocumentoAcessorioCrud = Crud.build(DocumentoAcessorio, '') +NumeracaoCrud = Crud.build(Numeracao, '') +OrgaoCrud = Crud.build(Orgao, 'orgao') +RelatoriaCrud = Crud.build(Relatoria, '') +TipoProposicaoCrud = Crud.build(TipoProposicao, 'tipo_proposicao') +ProposicaoCrud = Crud.build(Proposicao, '') +StatusTramitacaoCrud = Crud.build(StatusTramitacao, 'status_tramitacao') +UnidadeTramitacaoCrud = Crud.build(UnidadeTramitacao, 'unidade_tramitacao') +TramitacaoCrud = Crud.build(Tramitacao, '') class FormularioSimplificadoView(CreateView): @@ -1423,7 +1424,7 @@ class ProposicaoTaView(IntegracaoTaView): model_type_foreignkey = TipoProposicao -class AcompanhamentoMateriaView(materia_legislativa_crud.CrudDetailView): +class AcompanhamentoMateriaView(MateriaLegislativaCrud.CrudDetailView): template_name = "materia/acompanhamento_materia.html" def get_random_chars(self): diff --git a/norma/forms.py b/norma/forms.py index de90b6893..4b4c850d3 100644 --- a/norma/forms.py +++ b/norma/forms.py @@ -1,6 +1,7 @@ from crispy_forms.helper import FormHelper from crispy_forms.layout import Fieldset, Layout from django import forms +from django.core.exceptions import ValidationError from django.forms import ModelForm from django.utils.safestring import mark_safe @@ -39,14 +40,14 @@ class NormaJuridicaPesquisaForm(ModelForm): format='%d/%m/%Y', attrs={'class': 'dateinput'})) - publicação_inicial = forms.DateField(label=u'Publicação Inicial', + 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'})) - publicação_final = forms.DateField(label=u'Publicação Final', + publicacao_final = forms.DateField(label=u'Publicação Final', input_formats=['%d/%m/%Y'], required=False, widget=forms.DateInput( @@ -60,8 +61,8 @@ class NormaJuridicaPesquisaForm(ModelForm): 'ano', 'periodo_inicial', 'periodo_final', - 'publicação_inicial', - 'publicação_final'] + 'publicacao_inicial', + 'publicacao_final'] def __init__(self, *args, **kwargs): @@ -75,7 +76,7 @@ class NormaJuridicaPesquisaForm(ModelForm): [('periodo_inicial', 6), ('periodo_final', 6)]) row4 = crispy_layout_mixin.to_row( - [('publicação_inicial', 6), ('publicação_final', 6)]) + [('publicacao_inicial', 6), ('publicacao_final', 6)]) self.helper = FormHelper() self.helper.layout = Layout( @@ -99,6 +100,15 @@ class NormaJuridicaForm(ModelForm): ano_materia = forms.CharField(label='Ano', required=False) + def clean_texto_integral(self): + texto_integral = self.cleaned_data.get('texto_integral', False) + if texto_integral: + if texto_integral.size > 5*1024*1024: + raise ValidationError("Arquivo muito grande. ( > 5mb )") + return texto_integral + else: + raise ValidationError("Não foi possível salvar o arquivo.") + class Meta: model = NormaJuridica fields = ['tipo', diff --git a/norma/urls.py b/norma/urls.py index 2b93767eb..ad3edf43a 100644 --- a/norma/urls.py +++ b/norma/urls.py @@ -1,23 +1,31 @@ from django.conf.urls import include, url -from norma.views import (NormaEditView, NormaIncluirView, NormaPesquisaView, - NormaTaView, PesquisaNormaListView, - assunto_norma_crud, norma_temporario_crud, - tipo_norma_crud) +from norma.views import (AssuntoNormaCrud, NormaEditView, NormaIncluirView, + NormaPesquisaView, NormaTaView, NormaTemporarioCrud, + PesquisaNormaListView, TipoNormaCrud) -# norma_url_patterns = norma_crud.urlpatterns + [] -norma_url_patterns = norma_temporario_crud.urlpatterns + [ +# @LeandroRoberto comentou em +# https://github.com/interlegis/sapl/pull/255#discussion_r55894269 +# +# esse código só está assim de forma temporária, criado no início do +# projeto para apenas dar uma tela básica de listagem de normas para a app +# compilação... a implementação da app norma é independente e não sei em +# que estágio está... para a compilação é relevante apenas que se mantenha +# o código abaixo: +# url(r'^norma/(?P[0-9]+)/ta$', NormaTaView.as_view(), name='ta') +# bem como a classe NormaTaView que está em norma.views +norma_url_patterns, namespace = NormaTemporarioCrud.get_urls() + +norma_url_patterns += [ url(r'^norma/(?P[0-9]+)/ta$', NormaTaView.as_view(), name='ta') ] urlpatterns = [ - url(r'^norma/', include(norma_url_patterns, - norma_temporario_crud.namespace, - norma_temporario_crud.namespace)), + url(r'^norma/', include(norma_url_patterns, namespace)), - url(r'^sistema/norma/tipo/', include(tipo_norma_crud.urls)), - url(r'^sistema/norma/assunto/', include(assunto_norma_crud.urls)), + url(r'^sistema/norma/tipo/', include(TipoNormaCrud.get_urls())), + url(r'^sistema/norma/assunto/', include(AssuntoNormaCrud.get_urls())), url(r'^norma/incluir$', NormaIncluirView.as_view(), name='norma_incluir'), url(r'^norma/(?P[0-9]+)/editar$', diff --git a/norma/views.py b/norma/views.py index 46c6b4b82..32f5eb9a5 100644 --- a/norma/views.py +++ b/norma/views.py @@ -8,18 +8,18 @@ from django.shortcuts import redirect from django.views.generic import CreateView, FormView, ListView from compilacao.views import IntegracaoTaView -from crud import Crud, make_pagination +from crud.base import Crud, make_pagination from materia.models import MateriaLegislativa from .forms import NormaJuridicaForm, NormaJuridicaPesquisaForm from .models import (AssuntoNorma, LegislacaoCitada, NormaJuridica, TipoNormaJuridica) -assunto_norma_crud = Crud(AssuntoNorma, 'assunto_norma_juridica') -tipo_norma_crud = Crud(TipoNormaJuridica, 'tipo_norma_juridica') -norma_crud = Crud(NormaJuridica, '') -norma_temporario_crud = Crud(NormaJuridica, 'normajuridica') -legislacao_citada_crud = Crud(LegislacaoCitada, '') +AssuntoNormaCrud = Crud.build(AssuntoNorma, 'assunto_norma_juridica') +TipoNormaCrud = Crud.build(TipoNormaJuridica, 'tipo_norma_juridica') +NormaCrud = Crud.build(NormaJuridica, '') +NormaTemporarioCrud = Crud.build(NormaJuridica, 'normajuridica') +LegislacaoCitadaCrud = Crud.build(LegislacaoCitada, '') class NormaPesquisaView(FormView): @@ -44,9 +44,9 @@ class NormaPesquisaView(FormView): 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['publicação_inicial'] and form.data['publicação_final']: - kwargs['publicação_inicial'] = form.data['publicação_inicial'] - kwargs['publicação_final'] = form.data['publicação_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'] request.session['kwargs'] = kwargs return redirect('list_pesquisa_norma') @@ -68,16 +68,16 @@ class PesquisaNormaListView(ListView): periodo_final = datetime.strptime( kwargs['periodo_final'], '%d/%m/%Y').strftime('%Y-%m-%d') - publicação_inicial = datetime.strptime( - kwargs['publicação_inicial'], + publicacao_inicial = datetime.strptime( + kwargs['publicacao_inicial'], '%d/%m/%Y').strftime('%Y-%m-%d') - publicação_final = datetime.strptime( - kwargs['publicação_final'], + 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=(publicação_inicial, publicação_final)) + data_publicacao__range=(publicacao_inicial, publicacao_final)) if 'periodo_inicial' in kwargs: inicial = datetime.strptime(kwargs['periodo_inicial'], @@ -87,10 +87,10 @@ class PesquisaNormaListView(ListView): normas = normas.filter(data__range=(inicial, final)) - if 'publicação_inicial' in kwargs: - inicial = datetime.strptime(kwargs['publicação_inicial'], + if 'publicacao_inicial' in kwargs: + inicial = datetime.strptime(kwargs['publicacao_inicial'], '%d/%m/%Y').strftime('%Y-%m-%d') - final = datetime.strptime(kwargs['publicação_final'], + final = datetime.strptime(kwargs['publicacao_final'], '%d/%m/%Y').strftime('%Y-%m-%d') normas = normas.filter(data_publicacao__range=(inicial, final)) diff --git a/painel/urls.py b/painel/urls.py index 4b7e00bd5..1c7ad55f3 100644 --- a/painel/urls.py +++ b/painel/urls.py @@ -1,6 +1,6 @@ from django.conf.urls import url -from .views import controlador_painel # cronometro_painel_crud, +from .views import controlador_painel # CronometroPainelCrud, from .views import (cronometro_painel, get_dados_painel, painel_mensagem_view, painel_parlamentares_view, painel_view, painel_votacao_view) @@ -15,5 +15,5 @@ urlpatterns = [ name='painel_parlamentares'), url(r'^painel/votacao$', painel_votacao_view, name='painel_votacao'), url(r'^painel/cronometro$', cronometro_painel, name='cronometro_painel'), - # url(r'^painel/cronometro$', include(cronometro_painel_crud.urls)), + # url(r'^painel/cronometro$', include(CronometroPainelCrud.get_urls())), ] diff --git a/painel/views.py b/painel/views.py index b47945658..5a5398886 100644 --- a/painel/views.py +++ b/painel/views.py @@ -5,7 +5,7 @@ from django.http import HttpResponse, JsonResponse from django.shortcuts import render from django.utils.translation import ugettext_lazy as _ -from crud import Crud +from crud.base import Crud from painel.models import Painel from parlamentares.models import Filiacao from sessao.models import (ExpedienteMateria, OrdemDia, PresencaOrdemDia, @@ -14,7 +14,7 @@ from sessao.models import (ExpedienteMateria, OrdemDia, PresencaOrdemDia, from .models import Cronometro -cronometro_painel_crud = Crud(Cronometro, '') +CronometroPainelCrud = Crud.build(Cronometro, '') def controlador_painel(request): diff --git a/parlamentares/urls.py b/parlamentares/urls.py index a9180ddfc..e853c6908 100644 --- a/parlamentares/urls.py +++ b/parlamentares/urls.py @@ -1,35 +1,36 @@ from django.conf.urls import include, url -from parlamentares.views import (FiliacaoEditView, FiliacaoView, - MandatoEditView, MandatoView, - MesaDiretoraView, ParlamentaresCadastroView, +from parlamentares.views import (CargoMesaCrud, ColigacaoCrud, + FiliacaoEditView, FiliacaoView, + LegislaturaCrud, MandatoEditView, MandatoView, + MesaDiretoraView, NivelInstrucaoCrud, + ParlamentaresCadastroView, ParlamentaresDependentesEditView, ParlamentaresDependentesView, ParlamentaresEditarView, ParlamentaresView, - cargo_mesa_crud, coligacao_crud, - legislatura_crud, nivel_instrucao_crud, - partido_crud, sessao_legislativa_crud, - tipo_afastamento_crud, tipo_dependente_crud, - tipo_militar_crud) + PartidoCrud, SessaoLegislativaCrud, + TipoAfastamentoCrud, TipoDependenteCrud, + TipoMilitarCrud) urlpatterns = [ url(r'^sistema/parlamentares/legislatura/', - include(legislatura_crud.urls)), + include(LegislaturaCrud.get_urls())), url(r'^sistema/parlamentares/tipo-dependente/', - include(tipo_dependente_crud.urls)), + include(TipoDependenteCrud.get_urls())), url(r'^sistema/parlamentares/nivel-instrucao/', - include(nivel_instrucao_crud.urls)), - url(r'^sistema/parlamentares/coligacao/', include(coligacao_crud.urls)), + include(NivelInstrucaoCrud.get_urls())), + url(r'^sistema/parlamentares/coligacao/', + include(ColigacaoCrud.get_urls())), url(r'^sistema/parlamentares/tipo-afastamento/', - include(tipo_afastamento_crud.urls)), + include(TipoAfastamentoCrud.get_urls())), url(r'^sistema/parlamentares/tipo-militar/', - include(tipo_militar_crud.urls)), - url(r'^sistema/parlamentares/partido/', include(partido_crud.urls)), + include(TipoMilitarCrud.get_urls())), + url(r'^sistema/parlamentares/partido/', include(PartidoCrud.get_urls())), url(r'^sistema/mesa-diretora/sessao-legislativa/', - include(sessao_legislativa_crud.urls)), + include(SessaoLegislativaCrud.get_urls())), url(r'^sistema/mesa-diretora/cargo-mesa/', - include(cargo_mesa_crud.urls)), + include(CargoMesaCrud.get_urls())), url(r'^parlamentares/$', ParlamentaresView.as_view(), name='parlamentares'), diff --git a/parlamentares/views.py b/parlamentares/views.py index b22f95a31..c2350d70c 100644 --- a/parlamentares/views.py +++ b/parlamentares/views.py @@ -7,7 +7,7 @@ from django.http import HttpResponseRedirect from django.utils.translation import ugettext_lazy as _ from django.views.generic import CreateView, FormView, UpdateView -from crud import Crud +from crud.base import Crud from .forms import (DependenteEditForm, DependenteForm, FiliacaoEditForm, FiliacaoForm, MandatoEditForm, MandatoForm, @@ -18,19 +18,19 @@ from .models import (CargoMesa, Coligacao, ComposicaoMesa, Dependente, Parlamentar, Partido, SessaoLegislativa, SituacaoMilitar, TipoAfastamento, TipoDependente) -cargo_mesa_crud = Crud(CargoMesa, 'cargo_mesa') -legislatura_crud = Crud(Legislatura, 'tabelas_auxiliares#legislatura') -coligacao_crud = Crud(Coligacao, 'coligacao') -partido_crud = Crud(Partido, 'partidos') -dependente_crud = Crud(Dependente, '') -sessao_legislativa_crud = Crud(SessaoLegislativa, 'sessao_legislativa') -parlamentar_crud = Crud(Parlamentar, '') -filiacao_crud = Crud(Filiacao, '') -mandato_crud = Crud(Mandato, '') -tipo_dependente_crud = Crud(TipoDependente, 'tipo_dependente') -nivel_instrucao_crud = Crud(NivelInstrucao, 'nivel_instrucao') -tipo_afastamento_crud = Crud(TipoAfastamento, 'tipo_afastamento') -tipo_militar_crud = Crud(SituacaoMilitar, 'tipo_situa_militar') +CargoMesaCrud = Crud.build(CargoMesa, 'cargo_mesa') +LegislaturaCrud = Crud.build(Legislatura, 'tabelas_auxiliares#legislatura') +ColigacaoCrud = Crud.build(Coligacao, 'coligacao') +PartidoCrud = Crud.build(Partido, 'partidos') +DependenteCrud = Crud.build(Dependente, '') +SessaoLegislativaCrud = Crud.build(SessaoLegislativa, 'sessao_legislativa') +ParlamentarCrud = Crud.build(Parlamentar, '') +FiliacaoCrud = Crud.build(Filiacao, '') +MandatoCrud = Crud.build(Mandato, '') +TipoDependenteCrud = Crud.build(TipoDependente, 'tipo_dependente') +NivelInstrucaoCrud = Crud.build(NivelInstrucao, 'nivel_instrucao') +TipoAfastamentoCrud = Crud.build(TipoAfastamento, 'tipo_afastamento') +TipoMilitarCrud = Crud.build(SituacaoMilitar, 'tipo_situa_militar') class ParlamentaresView(FormView): diff --git a/protocoloadm/forms.py b/protocoloadm/forms.py index e801fe18a..81ac2dfb8 100644 --- a/protocoloadm/forms.py +++ b/protocoloadm/forms.py @@ -14,9 +14,9 @@ from crispy_layout_mixin import form_actions from materia.models import TipoMateriaLegislativa from sapl.utils import RANGE_ANOS -from .models import (Autor, DocumentoAcessorioAdministrativo, - DocumentoAdministrativo, Protocolo, - TipoDocumentoAdministrativo, TramitacaoAdministrativo) +from .models import (DocumentoAcessorioAdministrativo, DocumentoAdministrativo, + Protocolo, TipoDocumentoAdministrativo, + TramitacaoAdministrativo) TIPOS_PROTOCOLO = [('0', 'Enviado'), ('1', 'Recebido')] diff --git a/protocoloadm/urls.py b/protocoloadm/urls.py index bf8244ff9..51e98b2f9 100644 --- a/protocoloadm/urls.py +++ b/protocoloadm/urls.py @@ -4,40 +4,41 @@ from protocoloadm.views import (AnularProtocoloAdmView, ComprovanteProtocoloView, CriarDocumentoProtocolo, DetailDocumentoAdministrativo, + DocumentoAcessorioAdministrativoCrud, DocumentoAcessorioAdministrativoEditView, DocumentoAcessorioAdministrativoView, + DocumentoAdministrativoCrud, PesquisarDocumentoAdministrativo, ProposicaoDetailView, ProposicaoReceberView, ProposicaoView, ProposicoesIncorporadasView, ProposicoesNaoIncorporadasView, ProposicoesNaoRecebidasView, - ProtocoloDocumentoView, ProtocoloListView, + ProtocoloDocumentoCrud, ProtocoloDocumentoView, + ProtocoloListView, ProtocoloMateriaCrud, ProtocoloMateriaView, ProtocoloMostrarView, - ProtocoloPesquisaView, TramitacaoAdmDeleteView, - TramitacaoAdmEditView, - TramitacaoAdmIncluirView, TramitacaoAdmView, - documento_acessorio_administrativo_crud, - documento_administrativo_crud, - pesquisa_autores, protocolo_documento_crud, - protocolo_materia_crud, - status_tramitacao_administrativo_crud, - tipo_documento_administrativo_crud, - tramitacao_administrativo_crud) + ProtocoloPesquisaView, + StatusTramitacaoAdministrativoCrud, + TipoDocumentoAdministrativoCrud, + TramitacaoAdmDeleteView, TramitacaoAdmEditView, + TramitacaoAdmIncluirView, + TramitacaoAdministrativoCrud, + TramitacaoAdmView, pesquisa_autores) urlpatterns = [ - url(r'^protocoloadm/docadm/', include(documento_administrativo_crud.urls)), + url(r'^protocoloadm/docadm/', + include(DocumentoAdministrativoCrud.get_urls())), url(r'^protocoloadm/tipo-documento-adm/', - include(tipo_documento_administrativo_crud.urls)), + include(TipoDocumentoAdministrativoCrud.get_urls())), url(r'^protocoloadm/doc-acessorio/', - include(documento_acessorio_administrativo_crud.urls)), + include(DocumentoAcessorioAdministrativoCrud.get_urls())), url(r'^protocoloadm/status-tramitacao-adm/', - include(status_tramitacao_administrativo_crud.urls)), + include(StatusTramitacaoAdministrativoCrud.get_urls())), url(r'^protocoloadm/tramitacao-adm/', - include(tramitacao_administrativo_crud.urls)), + include(TramitacaoAdministrativoCrud.get_urls())), url(r'^protocoloadm/protocolo-doc/', - include(protocolo_documento_crud.urls)), + include(ProtocoloDocumentoCrud.get_urls())), url(r'^protocoloadm/protocolo-mat/', - include(protocolo_materia_crud.urls), name='protocolomat'), + include(ProtocoloMateriaCrud.get_urls()), name='protocolomat'), url(r'^protocoloadm/protocolo$', ProtocoloPesquisaView.as_view(), name='protocolo'), url(r'^protocoloadm/protocolo_list$', diff --git a/protocoloadm/views.py b/protocoloadm/views.py index 4c1bd8f6a..6153d9481 100644 --- a/protocoloadm/views.py +++ b/protocoloadm/views.py @@ -12,7 +12,7 @@ from django.utils.translation import ugettext_lazy as _ from django.views.generic import CreateView, DetailView, FormView, ListView from django.views.generic.base import TemplateView -from crud import Crud, make_pagination +from crud.base import Crud, make_pagination from materia.models import Proposicao, TipoMateriaLegislativa from sapl.utils import create_barcode, get_client_ip @@ -25,17 +25,18 @@ from .models import (Autor, DocumentoAcessorioAdministrativo, StatusTramitacaoAdministrativo, TipoDocumentoAdministrativo, TramitacaoAdministrativo) -tipo_documento_administrativo_crud = Crud(TipoDocumentoAdministrativo, '') -documento_administrativo_crud = Crud(DocumentoAdministrativo, '') -documento_acessorio_administrativo_crud = Crud( +TipoDocumentoAdministrativoCrud = Crud.build(TipoDocumentoAdministrativo, + '') +DocumentoAdministrativoCrud = Crud.build(DocumentoAdministrativo, '') +DocumentoAcessorioAdministrativoCrud = Crud.build( DocumentoAcessorioAdministrativo, '') -status_tramitacao_administrativo_crud = Crud( +StatusTramitacaoAdministrativoCrud = Crud.build( StatusTramitacaoAdministrativo, '') -tramitacao_administrativo_crud = Crud(TramitacaoAdministrativo, '') -protocolo_documento_crud = Crud(Protocolo, '') +TramitacaoAdministrativoCrud = Crud.build(TramitacaoAdministrativo, '') +ProtocoloDocumentoCrud = Crud.build(Protocolo, '') # FIXME precisa de uma chave diferente para o layout -protocolo_materia_crud = Crud(Protocolo, '') +ProtocoloMateriaCrud = Crud.build(Protocolo, '') class ProtocoloPesquisaView(FormView): @@ -139,7 +140,7 @@ class AnularProtocoloAdmView(FormView): protocolo = Protocolo.objects.get(numero=numero, ano=ano) protocolo.anulado = True protocolo.justificativa_anulacao = sub(' ', ' ', strip_tags( - form.cleaned_data['justificativa_anulacao'])) + form.cleaned_data['justificativa_anulacao'])) protocolo.user_anulacao = form.cleaned_data['user_anulacao'] protocolo.ip_anulacao = form.cleaned_data['ip_anulacao'] protocolo.save() diff --git a/pytest.ini b/pytest.ini index a3b1eef1f..12ce443ad 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,6 +1,6 @@ [pytest] DJANGO_SETTINGS_MODULE=sapl.settings -norecursedirs = legacy crud_tests +norecursedirs = legacy crud # REUSING DATABASE BY DEFAULT (as a performance optimization) # http://pytest-django.readthedocs.org/en/latest/database.html#example-work-flow-with-reuse-db-and-create-db diff --git a/relatorios/views.py b/relatorios/views.py index d6ccf435c..f07cb2b4f 100644 --- a/relatorios/views.py +++ b/relatorios/views.py @@ -26,6 +26,7 @@ from .templates import (pdf_capa_processo_gerar, uf_dic = dict(UF) + def get_kwargs_params(request, fields): kwargs = {} for i in fields: diff --git a/sessao/forms.py b/sessao/forms.py index 4b2367e52..79d8c458c 100644 --- a/sessao/forms.py +++ b/sessao/forms.py @@ -1,6 +1,7 @@ from crispy_forms.helper import FormHelper from crispy_forms.layout import Fieldset, Layout from django import forms +from django.core.exceptions import ValidationError from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ @@ -92,6 +93,24 @@ class SessaoForm(ModelForm): 'hora_fim': forms.TextInput(attrs={'class': 'hora'}), } + def clean_url_audio(self): + url_audio = self.cleaned_data.get('url_audio', False) + if url_audio: + if url_audio.size > 5*1024*1024: + raise ValidationError("Arquivo muito grande. ( > 5mb )") + return url_audio + else: + raise ValidationError("Não foi possível salvar o arquivo.") + + def clean_url_video(self): + url_video = self.cleaned_data.get('url_video', False) + if url_video: + if url_video.size > 5*1024*1024: + raise ValidationError("Arquivo muito grande. ( > 5mb )") + return url_video + else: + raise ValidationError("Não foi possível salvar o arquivo.") + def __init__(self, *args, **kwargs): row1 = crispy_layout_mixin.to_row( diff --git a/sessao/urls.py b/sessao/urls.py index 45e7f7c1c..95fba3701 100644 --- a/sessao/urls.py +++ b/sessao/urls.py @@ -12,16 +12,18 @@ from sessao.views import (EditExpedienteOrdemDiaView, EditMateriaOrdemDiaView, PautaExpedienteDetail, PautaOrdemDetail, PautaSessaoDetailView, PautaSessaoListView, PresencaOrdemDiaView, PresencaView, ResumoView, - SessaoCadastroView, SessaoListView, - SessaoPlenariaView, VotacaoEditView, - VotacaoExpedienteEditView, VotacaoExpedienteView, - VotacaoNominalEditView, + SessaoCadastroView, SessaoCrud, SessaoListView, + SessaoPlenariaView, TipoExpedienteCrud, + TipoResultadoVotacaoCrud, TipoSessaoCrud, + VotacaoEditView, VotacaoExpedienteEditView, + VotacaoExpedienteView, VotacaoNominalEditView, VotacaoNominalExpedienteEditView, VotacaoNominalExpedienteView, VotacaoNominalView, - VotacaoView, sessao_crud, tipo_expediente_crud, - tipo_resultado_votacao_crud, tipo_sessao_crud) + VotacaoView) -urlpatterns_sessao = sessao_crud.urlpatterns + [ +urlpatterns_sessao, namespace = SessaoCrud.get_urls() + +urlpatterns_sessao = urlpatterns_sessao + [ url(r'^(?P\d+)/expediente$', ExpedienteView.as_view(), name='expediente'), url(r'^(?P\d+)/presenca$', @@ -98,21 +100,19 @@ urlpatterns_sessao = sessao_crud.urlpatterns + [ PautaOrdemDetail.as_view(), name='pauta_ordem_detail'), ] -sessao_urls = urlpatterns_sessao, sessao_crud.namespace, sessao_crud.namespace - sessao_rest = [ url(r'^sessao$', SessaoPlenariaView.as_view(), name='sessao_rest') ] urlpatterns = [ - url(r'^sessao/', include(urlpatterns_sessao, - sessao_crud.namespace, sessao_crud.namespace)), + url(r'^sessao/', include(urlpatterns_sessao, namespace)), url(r'^media/(?P.*)$', serve, {'document_root': settings.MEDIA_ROOT}), url(r'^rest/', include(sessao_rest)), - url(r'^sistema/sessao-plenaria/tipo/', include(tipo_sessao_crud.urls)), + url(r'^sistema/sessao-plenaria/tipo/', + include(TipoSessaoCrud.get_urls())), url(r'^sistema/sessao-plenaria/tipo-resultado-votacao/', - include(tipo_resultado_votacao_crud.urls)), + include(TipoResultadoVotacaoCrud.get_urls())), url(r'^sistema/sessao-plenaria/tipo-expediente/', - include(tipo_expediente_crud.urls)) + include(TipoExpedienteCrud.get_urls())) ] diff --git a/sessao/views.py b/sessao/views.py index 93588e01d..70dc2aef2 100644 --- a/sessao/views.py +++ b/sessao/views.py @@ -11,7 +11,7 @@ from django.views.generic import CreateView, ListView from django.views.generic.edit import FormMixin from rest_framework import generics -from crud import Crud, make_pagination +from crud.base import Crud, make_pagination from materia.models import (Autoria, DocumentoAcessorio, TipoMateriaLegislativa, Tramitacao) from norma.models import NormaJuridica @@ -29,14 +29,14 @@ from .models import (CargoMesa, ExpedienteMateria, ExpedienteSessao, TipoExpediente, TipoResultadoVotacao, TipoSessaoPlenaria, VotoParlamentar) -tipo_sessao_crud = Crud(TipoSessaoPlenaria, 'tipo_sessao_plenaria') -sessao_crud = Crud(SessaoPlenaria, '') -expediente_materia_crud = Crud(ExpedienteMateria, '') -ordem_dia_crud = Crud(OrdemDia, '') -tipo_resultado_votacao_crud = Crud( +TipoSessaoCrud = Crud.build(TipoSessaoPlenaria, 'tipo_sessao_plenaria') +SessaoCrud = Crud.build(SessaoPlenaria, '') +ExpedienteMateriaCrud = Crud.build(ExpedienteMateria, '') +OrdemDiaCrud = Crud.build(OrdemDia, '') +TipoResultadoVotacaoCrud = Crud.build( TipoResultadoVotacao, 'tipo_resultado_votacao') -tipo_expediente_crud = Crud(TipoExpediente, 'tipo_expediente') -registro_votacao_crud = Crud(RegistroVotacao, '') +TipoExpedienteCrud = Crud.build(TipoExpediente, 'tipo_expediente') +RegistroVotacaoCrud = Crud.build(RegistroVotacao, '') class PresencaMixin: @@ -56,7 +56,7 @@ class PresencaMixin: yield (parlamentar, False) -class PresencaView(FormMixin, PresencaMixin, sessao_crud.CrudDetailView): +class PresencaView(FormMixin, PresencaMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/presenca.html' form_class = PresencaForm @@ -96,13 +96,13 @@ class PresencaView(FormMixin, PresencaMixin, sessao_crud.CrudDetailView): return reverse('sessaoplenaria:presenca', kwargs={'pk': pk}) -class PainelView(sessao_crud.CrudDetailView): +class PainelView(SessaoCrud.CrudDetailView): template_name = 'sessao/painel.html' class PresencaOrdemDiaView(FormMixin, PresencaMixin, - sessao_crud.CrudDetailView): + SessaoCrud.CrudDetailView): template_name = 'sessao/presenca_ordemdia.html' form_class = PresencaForm @@ -145,7 +145,7 @@ class PresencaOrdemDiaView(FormMixin, return reverse('sessaoplenaria:presencaordemdia', kwargs={'pk': pk}) -class ListMateriaOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): +class ListMateriaOrdemDiaView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/materia_ordemdia_list.html' form_class = ListMateriaForm @@ -248,7 +248,7 @@ class ListMateriaOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): return self.get(self, request, args, kwargs) -class ListExpedienteOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): +class ListExpedienteOrdemDiaView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/expediente_ordemdia_list.html' form_class = ListMateriaForm @@ -349,7 +349,7 @@ class ListExpedienteOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): return self.get(self, request, args, kwargs) -class MateriaOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): +class MateriaOrdemDiaView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/materia_ordemdia.html' form_class = MateriaOrdemDiaForm @@ -413,7 +413,7 @@ class MateriaOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): kwargs={'pk': pk}) -class EditMateriaOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): +class EditMateriaOrdemDiaView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/materia_ordemdia_edit.html' form_class = MateriaOrdemDiaForm @@ -524,7 +524,7 @@ class EditMateriaOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): kwargs={'pk': pk}) -class ExpedienteOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): +class ExpedienteOrdemDiaView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/materia_ordemdia.html' form_class = MateriaOrdemDiaForm @@ -590,7 +590,7 @@ class ExpedienteOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): kwargs={'pk': pk}) -class EditExpedienteOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): +class EditExpedienteOrdemDiaView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/materia_ordemdia_edit.html' form_class = MateriaOrdemDiaForm @@ -673,7 +673,7 @@ class EditExpedienteOrdemDiaView(FormMixin, sessao_crud.CrudDetailView): kwargs={'pk': pk}) -class OradorExpedienteDelete(FormMixin, sessao_crud.CrudDetailView): +class OradorExpedienteDelete(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/delete_orador.html' form_class = OradorDeleteForm @@ -698,7 +698,7 @@ class OradorExpedienteDelete(FormMixin, sessao_crud.CrudDetailView): return reverse('sessaoplenaria:oradorexpediente', kwargs={'pk': pk}) -class OradorExpedienteEdit(FormMixin, sessao_crud.CrudDetailView): +class OradorExpedienteEdit(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/edit_orador.html' form_class = OradorForm @@ -758,7 +758,7 @@ class OradorExpedienteEdit(FormMixin, sessao_crud.CrudDetailView): return reverse('sessaoplenaria:oradorexpediente', kwargs={'pk': pk}) -class OradorExpedienteView(FormMixin, sessao_crud.CrudDetailView): +class OradorExpedienteView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/orador_expediente.html' form_class = OradorForm @@ -828,7 +828,7 @@ class OradorExpedienteView(FormMixin, sessao_crud.CrudDetailView): return reverse('sessaoplenaria:oradorexpediente', kwargs={'pk': pk}) -class MesaView(FormMixin, sessao_crud.CrudDetailView): +class MesaView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/mesa.html' form_class = MesaForm @@ -922,7 +922,7 @@ class MesaView(FormMixin, sessao_crud.CrudDetailView): return reverse('sessaoplenaria:mesa', kwargs={'pk': pk}) -class ResumoView(sessao_crud.CrudDetailView): +class ResumoView(SessaoCrud.CrudDetailView): template_name = 'sessao/resumo.html' def get(self, request, *args, **kwargs): @@ -1098,7 +1098,7 @@ class ResumoView(sessao_crud.CrudDetailView): return self.render_to_response(context) -class ExpedienteView(FormMixin, sessao_crud.CrudDetailView): +class ExpedienteView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/expediente.html' form_class = ExpedienteForm @@ -1162,7 +1162,7 @@ class ExpedienteView(FormMixin, sessao_crud.CrudDetailView): return reverse('sessaoplenaria:expediente', kwargs={'pk': pk}) -class ExplicacaoView(FormMixin, sessao_crud.CrudDetailView): +class ExplicacaoView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/explicacao.html' form_class = OradorForm @@ -1232,7 +1232,7 @@ class ExplicacaoView(FormMixin, sessao_crud.CrudDetailView): return reverse('sessaoplenaria:explicacao', kwargs={'pk': pk}) -class ExplicacaoDelete(FormMixin, sessao_crud.CrudDetailView): +class ExplicacaoDelete(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/delete_explicacao.html' form_class = OradorDeleteForm @@ -1255,7 +1255,7 @@ class ExplicacaoDelete(FormMixin, sessao_crud.CrudDetailView): return reverse('sessaoplenaria:explicacao', kwargs={'pk': pk}) -class ExplicacaoEdit(FormMixin, sessao_crud.CrudDetailView): +class ExplicacaoEdit(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/edit_explicacao.html' form_class = OradorForm @@ -1315,7 +1315,7 @@ class ExplicacaoEdit(FormMixin, sessao_crud.CrudDetailView): return reverse('sessaoplenaria:explicacao', kwargs={'pk': pk}) -class VotacaoEditView(FormMixin, sessao_crud.CrudDetailView): +class VotacaoEditView(FormMixin, SessaoCrud.CrudDetailView): ''' Votação Simbólica e Secreta @@ -1388,7 +1388,7 @@ class VotacaoEditView(FormMixin, sessao_crud.CrudDetailView): kwargs={'pk': pk}) -class VotacaoView(FormMixin, sessao_crud.CrudDetailView): +class VotacaoView(FormMixin, SessaoCrud.CrudDetailView): ''' Votação Simbólica e Secreta @@ -1507,7 +1507,7 @@ class VotacaoView(FormMixin, sessao_crud.CrudDetailView): kwargs={'pk': pk}) -class VotacaoNominalView(FormMixin, sessao_crud.CrudDetailView): +class VotacaoNominalView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/votacao/nominal.html' def get(self, request, *args, **kwargs): @@ -1634,7 +1634,7 @@ class VotacaoNominalView(FormMixin, sessao_crud.CrudDetailView): kwargs={'pk': pk}) -class VotacaoNominalEditView(FormMixin, sessao_crud.CrudDetailView): +class VotacaoNominalEditView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/votacao/nominal_edit.html' def get(self, request, *args, **kwargs): @@ -1711,7 +1711,7 @@ class VotacaoNominalEditView(FormMixin, sessao_crud.CrudDetailView): kwargs={'pk': pk}) -class VotacaoNominalExpedienteView(FormMixin, sessao_crud.CrudDetailView): +class VotacaoNominalExpedienteView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/votacao/nominal.html' def get(self, request, *args, **kwargs): @@ -1836,7 +1836,7 @@ class VotacaoNominalExpedienteView(FormMixin, sessao_crud.CrudDetailView): kwargs={'pk': pk}) -class VotacaoNominalExpedienteEditView(FormMixin, sessao_crud.CrudDetailView): +class VotacaoNominalExpedienteEditView(FormMixin, SessaoCrud.CrudDetailView): template_name = 'sessao/votacao/nominal_edit.html' def get(self, request, *args, **kwargs): @@ -1913,7 +1913,7 @@ class VotacaoNominalExpedienteEditView(FormMixin, sessao_crud.CrudDetailView): kwargs={'pk': pk}) -class VotacaoExpedienteView(FormMixin, sessao_crud.CrudDetailView): +class VotacaoExpedienteView(FormMixin, SessaoCrud.CrudDetailView): ''' Votação Simbólica e Secreta @@ -2034,7 +2034,7 @@ class VotacaoExpedienteView(FormMixin, sessao_crud.CrudDetailView): kwargs={'pk': pk}) -class VotacaoExpedienteEditView(FormMixin, sessao_crud.CrudDetailView): +class VotacaoExpedienteEditView(FormMixin, SessaoCrud.CrudDetailView): ''' Votação Simbólica e Secreta @@ -2133,7 +2133,7 @@ class PautaSessaoListView(SessaoListView): template_name = "sessao/pauta_sessao_list.html" -class PautaSessaoDetailView(sessao_crud.CrudDetailView): +class PautaSessaoDetailView(SessaoCrud.CrudDetailView): template_name = "sessao/pauta_sessao_detail.html" def get(self, request, *args, **kwargs): @@ -2245,7 +2245,7 @@ class SessaoPlenariaView(generics.ListAPIView): serializer_class = SessaoPlenariaSerializer -class PautaExpedienteDetail(sessao_crud.CrudDetailView): +class PautaExpedienteDetail(SessaoCrud.CrudDetailView): template_name = "sessao/pauta/expediente.html" def get(self, request, *args, **kwargs): @@ -2263,7 +2263,7 @@ class PautaExpedienteDetail(sessao_crud.CrudDetailView): 'tramitacao': tramitacao}) -class PautaOrdemDetail(sessao_crud.CrudDetailView): +class PautaOrdemDetail(SessaoCrud.CrudDetailView): template_name = "sessao/pauta/ordem.html" def get(self, request, *args, **kwargs): diff --git a/test_and_check_qa.sh b/test_and_check_qa.sh index c1753337c..4e9ff8dd4 100755 --- a/test_and_check_qa.sh +++ b/test_and_check_qa.sh @@ -3,5 +3,5 @@ # QA checks: run this before every commit py.test -py.test --ds=crud_tests.settings crud_tests +py.test --ds=crud.tests.settings crud/tests ./check_qa.sh From b214cd82efbc673bffcd06108208fe74e07baabc Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Wed, 16 Mar 2016 12:32:10 -0300 Subject: [PATCH 07/27] Valida Texto de Ata e Pauta de Sessao. Retira validacao de URL de video e audio, pois nao sao arquivos e sim links --- sessao/forms.py | 18 ------------------ sessao/models.py | 8 +++++--- 2 files changed, 5 insertions(+), 21 deletions(-) diff --git a/sessao/forms.py b/sessao/forms.py index 79d8c458c..df819ceef 100644 --- a/sessao/forms.py +++ b/sessao/forms.py @@ -93,24 +93,6 @@ class SessaoForm(ModelForm): 'hora_fim': forms.TextInput(attrs={'class': 'hora'}), } - def clean_url_audio(self): - url_audio = self.cleaned_data.get('url_audio', False) - if url_audio: - if url_audio.size > 5*1024*1024: - raise ValidationError("Arquivo muito grande. ( > 5mb )") - return url_audio - else: - raise ValidationError("Não foi possível salvar o arquivo.") - - def clean_url_video(self): - url_video = self.cleaned_data.get('url_video', False) - if url_video: - if url_video.size > 5*1024*1024: - raise ValidationError("Arquivo muito grande. ( > 5mb )") - return url_video - else: - raise ValidationError("Não foi possível salvar o arquivo.") - def __init__(self, *args, **kwargs): row1 = crispy_layout_mixin.to_row( diff --git a/sessao/models.py b/sessao/models.py index e38e87f63..2d59a13e5 100644 --- a/sessao/models.py +++ b/sessao/models.py @@ -5,7 +5,7 @@ from model_utils import Choices from materia.models import MateriaLegislativa from parlamentares.models import (CargoMesa, Legislatura, Parlamentar, SessaoLegislativa) -from sapl.utils import YES_NO_CHOICES +from sapl.utils import restringe_tipos_de_arquivo_txt, YES_NO_CHOICES class TipoSessaoPlenaria(models.Model): @@ -63,12 +63,14 @@ class SessaoPlenaria(models.Model): blank=True, null=True, upload_to=pauta_upload_path, - verbose_name=_('Pauta da Sessão')) + verbose_name=_('Pauta da Sessão'), + validators=[restringe_tipos_de_arquivo_txt]) upload_ata = models.FileField( blank=True, null=True, upload_to=ata_upload_path, - verbose_name=_('Ata da Sessão')) + verbose_name=_('Ata da Sessão'), + validators=[restringe_tipos_de_arquivo_txt]) iniciada = models.NullBooleanField(blank=True, choices=YES_NO_CHOICES, verbose_name=_('Sessão iniciada?')) From 596af6dab6292c90da6497456a383e1018efb680 Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Wed, 16 Mar 2016 12:49:52 -0300 Subject: [PATCH 08/27] Ajusta layout de Proposicoes e Sessao Legislativa --- templates/materia/proposicao/proposicao_list.html | 14 +++++++------- templates/sessao/sessao_list.html | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/templates/materia/proposicao/proposicao_list.html b/templates/materia/proposicao/proposicao_list.html index d666badbe..cb04c5bf0 100644 --- a/templates/materia/proposicao/proposicao_list.html +++ b/templates/materia/proposicao/proposicao_list.html @@ -3,16 +3,16 @@ {% load crispy_forms_tags %} {% block actions %}{% endblock %} - + {% block detail_content %} + +

Proposições

diff --git a/templates/sessao/sessao_list.html b/templates/sessao/sessao_list.html index e005802a1..f85faa389 100644 --- a/templates/sessao/sessao_list.html +++ b/templates/sessao/sessao_list.html @@ -3,8 +3,8 @@ {% load crispy_forms_tags %} {% block base_content %} +

Sessões Plenárias

-

Sessões Plenárias

{% blocktrans with verbose_name=view.verbose_name %} Adicionar Sessão Plenária {% endblocktrans %} From 1200b361e02043a7cbca1d912e814db14501c70b Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Wed, 16 Mar 2016 13:05:28 -0300 Subject: [PATCH 09/27] Faz ajustes apos os testes automaticos --- materia/models.py | 4 ++-- materia/views.py | 1 - parlamentares/models.py | 2 +- parlamentares/views.py | 3 +-- sapl/utils.py | 3 +-- sessao/forms.py | 1 - sessao/models.py | 2 +- 7 files changed, 6 insertions(+), 10 deletions(-) diff --git a/materia/models.py b/materia/models.py index 724c7f5ae..bcf63e53f 100644 --- a/materia/models.py +++ b/materia/models.py @@ -4,8 +4,8 @@ from model_utils import Choices from comissoes.models import Comissao from parlamentares.models import Parlamentar, Partido -from sapl.utils import (restringe_tipos_de_arquivo_txt, - RANGE_ANOS, YES_NO_CHOICES, xstr) +from sapl.utils import (RANGE_ANOS, YES_NO_CHOICES, + restringe_tipos_de_arquivo_txt, xstr) class TipoMateriaLegislativa(models.Model): diff --git a/materia/views.py b/materia/views.py index d71e8908d..36c4dbd6e 100644 --- a/materia/views.py +++ b/materia/views.py @@ -1,5 +1,4 @@ import os - from datetime import datetime from random import choice from string import ascii_letters, digits diff --git a/parlamentares/models.py b/parlamentares/models.py index 6842ced10..bb97e40d7 100644 --- a/parlamentares/models.py +++ b/parlamentares/models.py @@ -4,7 +4,7 @@ from django.db import models from django.utils.translation import ugettext_lazy as _ from model_utils import Choices -from sapl.utils import restringe_tipos_de_arquivo_img, UF, YES_NO_CHOICES +from sapl.utils import UF, YES_NO_CHOICES, restringe_tipos_de_arquivo_img class Legislatura(models.Model): diff --git a/parlamentares/views.py b/parlamentares/views.py index c2350d70c..75e3fe3f2 100644 --- a/parlamentares/views.py +++ b/parlamentares/views.py @@ -1,11 +1,10 @@ import os -from braces.views import FormMessagesMixin from django.contrib import messages from django.core.urlresolvers import reverse, reverse_lazy from django.http import HttpResponseRedirect from django.utils.translation import ugettext_lazy as _ -from django.views.generic import CreateView, FormView, UpdateView +from django.views.generic import FormView, UpdateView from crud.base import Crud diff --git a/sapl/utils.py b/sapl/utils.py index e06092ea9..6cef79ad0 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -1,13 +1,12 @@ from datetime import date - from functools import wraps +import magic from django.apps import apps from django.contrib import admin from django.core.exceptions import ValidationError from django.utils.translation import ugettext_lazy as _ -import magic autor_label = '''
diff --git a/sessao/forms.py b/sessao/forms.py index df819ceef..4b2367e52 100644 --- a/sessao/forms.py +++ b/sessao/forms.py @@ -1,7 +1,6 @@ from crispy_forms.helper import FormHelper from crispy_forms.layout import Fieldset, Layout from django import forms -from django.core.exceptions import ValidationError from django.forms import ModelForm from django.utils.translation import ugettext_lazy as _ diff --git a/sessao/models.py b/sessao/models.py index 2d59a13e5..6e7e2e86f 100644 --- a/sessao/models.py +++ b/sessao/models.py @@ -5,7 +5,7 @@ from model_utils import Choices from materia.models import MateriaLegislativa from parlamentares.models import (CargoMesa, Legislatura, Parlamentar, SessaoLegislativa) -from sapl.utils import restringe_tipos_de_arquivo_txt, YES_NO_CHOICES +from sapl.utils import YES_NO_CHOICES, restringe_tipos_de_arquivo_txt class TipoSessaoPlenaria(models.Model): From e7b8591ecde30a83c15bb4697772c9c76a231fb4 Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Tue, 8 Mar 2016 18:14:52 -0300 Subject: [PATCH 10/27] Integra o python-decouple --- decouple.env | 12 ++++++++++++ requirements/requirements.txt | 1 + sapl/settings.py | 26 ++++++++++++++------------ 3 files changed, 27 insertions(+), 12 deletions(-) create mode 100644 decouple.env diff --git a/decouple.env b/decouple.env new file mode 100644 index 000000000..341c5ff99 --- /dev/null +++ b/decouple.env @@ -0,0 +1,12 @@ +SECRET_KEY=!9g1-#la+#(oft(v-y1qhy$jk-2$24pdk69#b_jfqyv!*%a_)t +DEBUG=True +NAME=sapl +USER=sapl +PASSWORD=sapl +HOST=localhost +PORT=5432 +EMAIL_USE_TLS = True +EMAIL_HOST = '' +EMAIL_HOST_USER = '' +EMAIL_HOST_PASSWORD = '' +EMAIL_PORT = 587 \ No newline at end of file diff --git a/requirements/requirements.txt b/requirements/requirements.txt index fa666f49b..432561465 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -5,6 +5,7 @@ django-bower==5.1.0 django-braces==1.8.1 django-compressor==2.0 django-crispy-forms==1.6.0 +python-decouple==3.0 django-extra-views==0.7.1 django-model-utils==2.4 django-sass-processor==0.3.4 diff --git a/sapl/settings.py b/sapl/settings.py index 996a0824f..b6b4c5a6a 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -14,16 +14,18 @@ from unipath import Path from .temp_suppress_crispy_form_warnings import \ SUPRESS_CRISPY_FORM_WARNINGS_LOGGING +from decouple import config + BASE_DIR = Path(__file__).ancestor(2) # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = '!9g1-#la+#(oft(v-y1qhy$jk-2$24pdk69#b_jfqyv!*%a_)t' +SECRET_KEY = config('SECRET_KEY') # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = True +DEBUG = config('DEBUG', default=False, cast=bool) ALLOWED_HOSTS = ['*'] @@ -107,19 +109,19 @@ WSGI_APPLICATION = 'sapl.wsgi.application' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': 'sapl', - 'USER': 'sapl', - 'PASSWORD': 'sapl', - 'HOST': 'localhost', - 'PORT': '5432', + 'NAME': config('NAME'), + 'USER': config('USER'), + 'PASSWORD': config('PASSWORD'), + 'HOST': config('HOST'), + 'PORT': config('PORT'), } } -EMAIL_USE_TLS = True -EMAIL_HOST = '' -EMAIL_HOST_USER = '' -EMAIL_HOST_PASSWORD = '' -EMAIL_PORT = 587 +EMAIL_USE_TLS = config('EMAIL_USE_TLS') +EMAIL_HOST = config('EMAIL_HOST') +EMAIL_HOST_USER = config('EMAIL_HOST_USER') +EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD') +EMAIL_PORT = config('EMAIL_PORT', cast=int) MAX_DOC_UPLOAD_SIZE = 5*1024*1024 # 5MB MAX_IMAGE_UPLOAD_SIZE = 2*1024*1024 # 2MB From 1f8d10f8c2f44edaff0b04130f5e81ef1f91a798 Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Tue, 8 Mar 2016 19:46:20 -0300 Subject: [PATCH 11/27] Arruma o python-decouple --- decouple.env => sapl/decouple.env | 0 sapl/settings.py | 1 + sapl/test_config.py | 5 +++++ 3 files changed, 6 insertions(+) rename decouple.env => sapl/decouple.env (100%) create mode 100644 sapl/test_config.py diff --git a/decouple.env b/sapl/decouple.env similarity index 100% rename from decouple.env rename to sapl/decouple.env diff --git a/sapl/settings.py b/sapl/settings.py index b6b4c5a6a..cbaac9a7a 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -18,6 +18,7 @@ from decouple import config BASE_DIR = Path(__file__).ancestor(2) + # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/1.8/howto/deployment/checklist/ diff --git a/sapl/test_config.py b/sapl/test_config.py new file mode 100644 index 000000000..5231c76d2 --- /dev/null +++ b/sapl/test_config.py @@ -0,0 +1,5 @@ +from .settings import EMAIL_PORT + + +def test_config(): + assert EMAIL_PORT == 587 From 940cfb802a5d829d6c97331c004bd72e3585e3aa Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Thu, 10 Mar 2016 13:31:19 -0300 Subject: [PATCH 12/27] Implementa e testa o settings.py utilizando o python-decouple --- sapl/settings.py | 10 +++++----- sapl/test_config.py | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/sapl/settings.py b/sapl/settings.py index cbaac9a7a..b7f4ee978 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -111,17 +111,17 @@ DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': config('NAME'), - 'USER': config('USER'), + 'USER': config('SET_USER'), 'PASSWORD': config('PASSWORD'), 'HOST': config('HOST'), 'PORT': config('PORT'), } } -EMAIL_USE_TLS = config('EMAIL_USE_TLS') -EMAIL_HOST = config('EMAIL_HOST') -EMAIL_HOST_USER = config('EMAIL_HOST_USER') -EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD') +EMAIL_USE_TLS = config('EMAIL_USE_TLS', cast=bool) +EMAIL_HOST = config('EMAIL_HOST', cast=str) +EMAIL_HOST_USER = config('EMAIL_HOST_USER', cast=str) +EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD', cast=str) EMAIL_PORT = config('EMAIL_PORT', cast=int) MAX_DOC_UPLOAD_SIZE = 5*1024*1024 # 5MB diff --git a/sapl/test_config.py b/sapl/test_config.py index 5231c76d2..fa0f8e621 100644 --- a/sapl/test_config.py +++ b/sapl/test_config.py @@ -1,5 +1,25 @@ from .settings import EMAIL_PORT +from .settings import SECRET_KEY +from .settings import DEBUG +from .settings import DATABASES +from .settings import EMAIL_USE_TLS +from .settings import EMAIL_HOST +from .settings import EMAIL_HOST_USER +from .settings import EMAIL_HOST_PASSWORD + +data = DATABASES.get('default') def test_config(): assert EMAIL_PORT == 587 + assert SECRET_KEY == '!9g1-#la+#(oft(v-y1qhy$jk-2$24pdk69#b_jfqyv!*%a_)t' + assert DEBUG is True + assert data.get('NAME') == 'sapl' + assert data.get('USER') == 'sapl' + assert data.get('PASSWORD') == 'sapl' + assert data.get('HOST') == 'localhost' + assert data.get('PORT') == '5432' + assert EMAIL_USE_TLS is True + assert EMAIL_HOST == 'smtp.interlegis.leg.br' + assert EMAIL_HOST_USER == 'sapl-test' + assert EMAIL_HOST_PASSWORD == '2BhCwbGHcZ' From 70be77dcdc881100d3e026e02afb729e906e0427 Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Fri, 11 Mar 2016 14:01:02 -0300 Subject: [PATCH 13/27] Ajusta o uso do python-decouple --- requirements/requirements.txt | 2 +- sapl/settings.py | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/requirements/requirements.txt b/requirements/requirements.txt index 432561465..3e2575f11 100644 --- a/requirements/requirements.txt +++ b/requirements/requirements.txt @@ -1,4 +1,4 @@ - +dj-database-url django-admin-bootstrapped==2.5.7 django-bootstrap3==7.0.0 django-bower==5.1.0 diff --git a/sapl/settings.py b/sapl/settings.py index b7f4ee978..903a7a016 100644 --- a/sapl/settings.py +++ b/sapl/settings.py @@ -16,6 +16,8 @@ from .temp_suppress_crispy_form_warnings import \ from decouple import config +from dj_database_url import parse as db_url + BASE_DIR = Path(__file__).ancestor(2) @@ -108,14 +110,10 @@ WSGI_APPLICATION = 'sapl.wsgi.application' # https://docs.djangoproject.com/en/1.8/ref/settings/#databases DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.postgresql_psycopg2', - 'NAME': config('NAME'), - 'USER': config('SET_USER'), - 'PASSWORD': config('PASSWORD'), - 'HOST': config('HOST'), - 'PORT': config('PORT'), - } + 'default': config( + 'DATABASE_URL', + cast=db_url, + ) } EMAIL_USE_TLS = config('EMAIL_USE_TLS', cast=bool) From 2b310d8119dddf4a0af35b51d07e8f2c3ca7ae77 Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Fri, 11 Mar 2016 14:34:36 -0300 Subject: [PATCH 14/27] Coloca as instrucoes, no README, de como setar o settings.py usando o python decouple --- README.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.rst b/README.rst index dfd5a50d5..2db757c98 100644 --- a/README.rst +++ b/README.rst @@ -56,6 +56,19 @@ Development Environment Installation * Either run ``./manage.py migrate`` (for an empty database) or restore a database dump. +* In sapl/sapl directory create one file called ``.env``. Write the following attribuitions +in it: + +DATABASE_URL = postgresql://USER:PASSWORD@HOST:PORT/NAME +SECRET_KEY = Generate some key and paste here. You generate it using the link below. +DEBUG = [True/False] +EMAIL_USE_TLS = [True/False] +EMAIL_PORT = [Set this parameter] +EMAIL_HOST = [Set this parameter] +EMAIL_HOST_USER = [Set this parameter] +EMAIL_HOST_PASSWORD = [Set this parameter] + +`Generate your secret key here ` Instructions for Translators ============================ From ea405ba2e084736bbdb05941c059fe1f27319731 Mon Sep 17 00:00:00 2001 From: Eduardo Calil Date: Fri, 11 Mar 2016 14:36:21 -0300 Subject: [PATCH 15/27] Formata a atualizacao do README --- README.rst | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/README.rst b/README.rst index 2db757c98..637a90cd3 100644 --- a/README.rst +++ b/README.rst @@ -56,19 +56,18 @@ Development Environment Installation * Either run ``./manage.py migrate`` (for an empty database) or restore a database dump. -* In sapl/sapl directory create one file called ``.env``. Write the following attribuitions -in it: - -DATABASE_URL = postgresql://USER:PASSWORD@HOST:PORT/NAME -SECRET_KEY = Generate some key and paste here. You generate it using the link below. -DEBUG = [True/False] -EMAIL_USE_TLS = [True/False] -EMAIL_PORT = [Set this parameter] -EMAIL_HOST = [Set this parameter] -EMAIL_HOST_USER = [Set this parameter] -EMAIL_HOST_PASSWORD = [Set this parameter] - -`Generate your secret key here ` +* In ``sapl/sapl`` directory create one file called ``.env``. Write the following attributes in it: + + - DATABASE_URL = postgresql://USER:PASSWORD@HOST:PORT/NAME + - SECRET_KEY = Generate some key and paste here + - DEBUG = [True/False] + - EMAIL_USE_TLS = [True/False] + - EMAIL_PORT = [Set this parameter] + - EMAIL_HOST = [Set this parameter] + - EMAIL_HOST_USER = [Set this parameter] + - EMAIL_HOST_PASSWORD = [Set this parameter] + +`Generate your secret key here `_ Instructions for Translators ============================ From 94bd19db13fd4b360b6fcca259decbd17cc913fe Mon Sep 17 00:00:00 2001 From: eduardocalil Date: Fri, 11 Mar 2016 15:16:04 -0300 Subject: [PATCH 16/27] Delete decouple.env --- sapl/decouple.env | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 sapl/decouple.env diff --git a/sapl/decouple.env b/sapl/decouple.env deleted file mode 100644 index 341c5ff99..000000000 --- a/sapl/decouple.env +++ /dev/null @@ -1,12 +0,0 @@ -SECRET_KEY=!9g1-#la+#(oft(v-y1qhy$jk-2$24pdk69#b_jfqyv!*%a_)t -DEBUG=True -NAME=sapl -USER=sapl -PASSWORD=sapl -HOST=localhost -PORT=5432 -EMAIL_USE_TLS = True -EMAIL_HOST = '' -EMAIL_HOST_USER = '' -EMAIL_HOST_PASSWORD = '' -EMAIL_PORT = 587 \ No newline at end of file From ae180fa3378418ae27833759d737296d51d0bc25 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Thu, 31 Mar 2016 16:43:55 -0300 Subject: [PATCH 17/27] =?UTF-8?q?Remove=20teste=20desnecess=C3=A1rio?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/test_config.py | 25 ------------------------- 1 file changed, 25 deletions(-) delete mode 100644 sapl/test_config.py diff --git a/sapl/test_config.py b/sapl/test_config.py deleted file mode 100644 index fa0f8e621..000000000 --- a/sapl/test_config.py +++ /dev/null @@ -1,25 +0,0 @@ -from .settings import EMAIL_PORT -from .settings import SECRET_KEY -from .settings import DEBUG -from .settings import DATABASES -from .settings import EMAIL_USE_TLS -from .settings import EMAIL_HOST -from .settings import EMAIL_HOST_USER -from .settings import EMAIL_HOST_PASSWORD - -data = DATABASES.get('default') - - -def test_config(): - assert EMAIL_PORT == 587 - assert SECRET_KEY == '!9g1-#la+#(oft(v-y1qhy$jk-2$24pdk69#b_jfqyv!*%a_)t' - assert DEBUG is True - assert data.get('NAME') == 'sapl' - assert data.get('USER') == 'sapl' - assert data.get('PASSWORD') == 'sapl' - assert data.get('HOST') == 'localhost' - assert data.get('PORT') == '5432' - assert EMAIL_USE_TLS is True - assert EMAIL_HOST == 'smtp.interlegis.leg.br' - assert EMAIL_HOST_USER == 'sapl-test' - assert EMAIL_HOST_PASSWORD == '2BhCwbGHcZ' From 5e35b20c074bb25191edc61a0e083e1b06c6516f Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Fri, 1 Apr 2016 14:25:53 -0300 Subject: [PATCH 18/27] Conserta PEP8 --- base/forms.py | 25 +++++++++++++------------ sessao/forms.py | 1 - 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/base/forms.py b/base/forms.py index 23a7864e7..d0e660312 100644 --- a/base/forms.py +++ b/base/forms.py @@ -88,18 +88,19 @@ class CasaLegislativaTabelaAuxForm(ModelForm): row3, row4, row5, - HTML("""
- {% if not form.fotografia.errors and form.fotografia.value %} - -
- - {% endif %} -
"""), + HTML(""" +
+ {% if not form.fotografia.errors and form.fotografia.value %} + +
+ + {% endif %} +
"""), row6, row7, row8, diff --git a/sessao/forms.py b/sessao/forms.py index dd9c1ab34..4b2367e52 100644 --- a/sessao/forms.py +++ b/sessao/forms.py @@ -6,7 +6,6 @@ from django.utils.translation import ugettext_lazy as _ import crispy_layout_mixin from crispy_layout_mixin import form_actions -from sapl.settings import MAX_DOC_UPLOAD_SIZE from .models import SessaoPlenaria From e2f1efb1d9903b484b8b7b275428719e6c66608e Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Fri, 1 Apr 2016 14:57:58 -0300 Subject: [PATCH 19/27] Conserta bug no teste de parlamentar --- parlamentares/test_parlamentares.py | 5 ++--- parlamentares/views.py | 4 ---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/parlamentares/test_parlamentares.py b/parlamentares/test_parlamentares.py index e8ea6c3bc..f7a04fba7 100644 --- a/parlamentares/test_parlamentares.py +++ b/parlamentares/test_parlamentares.py @@ -12,13 +12,12 @@ def test_cadastro_parlamentar(client): response = client.get(reverse('parlamentares_cadastro', kwargs={'pk': 5})) assert response.status_code == 200 - response = client.post(reverse('parlamentares_cadastro', kwargs={'pk': 5}), {'nome_completo': 'Teresa Barbosa', 'nome_parlamentar': 'Terezinha', 'sexo': 'F', - 'ativo': 'True', - }) + 'ativo': 'True'}, follow=True) + parlamentar = Parlamentar.objects.first() assert "Terezinha" == parlamentar.nome_parlamentar if not parlamentar.ativo: diff --git a/parlamentares/views.py b/parlamentares/views.py index eda0452ec..63a53237a 100644 --- a/parlamentares/views.py +++ b/parlamentares/views.py @@ -186,10 +186,6 @@ class ParlamentaresCadastroView(CreateView): def form_valid(self, form): form.save() - mandato = Mandato() - mandato.parlamentar = form.instance - mandato.legislatura = Legislatura.objects.get(id=self.kwargs['pk']) - mandato.save() return redirect(self.get_success_url()) From 87607ad6b13e6a64e416b3d44804885fa171bdcf Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Mon, 4 Apr 2016 10:46:18 -0300 Subject: [PATCH 20/27] Cria teste para verificar campo null de CharField e TextField --- sapl/test_general.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sapl/test_general.py b/sapl/test_general.py index 443cc40d4..47a992aed 100644 --- a/sapl/test_general.py +++ b/sapl/test_general.py @@ -6,6 +6,18 @@ from .settings import SAPL_APPS pytestmark = pytest.mark.django_db +for model in apps.get_models(): + fields = model._meta.local_fields + for field in fields: + if (type(field).__name__ == 'CharField' or + type(field).__name__ == 'TextField'): + msg = 'Model = %s || Field = %s - %s - %s' % ( + model.__name__, + field.attname, + type(field).__name__, + field.null) + raise AssertionError(msg) + def test_str_sanity(): # this simply a sanity check From 4191bc5386ea2df3c9d8d3001cd514077660c313 Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Mon, 4 Apr 2016 10:57:11 -0300 Subject: [PATCH 21/27] =?UTF-8?q?Coloca=20teste=20de=20CharField=20e=20Tex?= =?UTF-8?q?tField=20em=20um=20m=C3=A9todo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/test_general.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/sapl/test_general.py b/sapl/test_general.py index 47a992aed..090052e51 100644 --- a/sapl/test_general.py +++ b/sapl/test_general.py @@ -6,17 +6,18 @@ from .settings import SAPL_APPS pytestmark = pytest.mark.django_db -for model in apps.get_models(): - fields = model._meta.local_fields - for field in fields: - if (type(field).__name__ == 'CharField' or - type(field).__name__ == 'TextField'): - msg = 'Model = %s || Field = %s - %s - %s' % ( - model.__name__, - field.attname, - type(field).__name__, - field.null) - raise AssertionError(msg) +def test_charfiled_textfield(): + for model in apps.get_models(): + fields = model._meta.local_fields + for field in fields: + if (type(field).__name__ == 'CharField' or + type(field).__name__ == 'TextField'): + msg = 'Model = %s || Field = %s - %s - %s' % ( + model.__name__, + field.attname, + type(field).__name__, + field.null) + raise AssertionError(msg) def test_str_sanity(): From ec469fd6e6c3d14787a52bc320b6d380fcce3863 Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Mon, 4 Apr 2016 11:09:52 -0300 Subject: [PATCH 22/27] =?UTF-8?q?Muda=20condi=C3=A7=C3=A3o=20para=20verifi?= =?UTF-8?q?car=20a=20instancia=20do=20campo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/test_general.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sapl/test_general.py b/sapl/test_general.py index 090052e51..8c3093bc8 100644 --- a/sapl/test_general.py +++ b/sapl/test_general.py @@ -1,4 +1,5 @@ import pytest +from django.db.models import CharField, TextField from django.apps import apps from model_mommy import mommy @@ -6,12 +7,12 @@ from .settings import SAPL_APPS pytestmark = pytest.mark.django_db + def test_charfiled_textfield(): for model in apps.get_models(): fields = model._meta.local_fields for field in fields: - if (type(field).__name__ == 'CharField' or - type(field).__name__ == 'TextField'): + if isinstance(field, (CharField, TextField)): msg = 'Model = %s || Field = %s - %s - %s' % ( model.__name__, field.attname, From d48f91f23f4b674502f5666143c761ad18b32ae6 Mon Sep 17 00:00:00 2001 From: Eduardo Edson Batista Cordeiro Alves Date: Mon, 4 Apr 2016 11:53:03 -0300 Subject: [PATCH 23/27] =?UTF-8?q?Muda=20forma=20que=20o=20assert=20=C3=A9?= =?UTF-8?q?=20feito?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sapl/test_general.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sapl/test_general.py b/sapl/test_general.py index 8c3093bc8..dac87ffa1 100644 --- a/sapl/test_general.py +++ b/sapl/test_general.py @@ -7,24 +7,26 @@ from .settings import SAPL_APPS pytestmark = pytest.mark.django_db +sapl_appconfs = [apps.get_app_config(n) for n in SAPL_APPS] + def test_charfiled_textfield(): - for model in apps.get_models(): - fields = model._meta.local_fields - for field in fields: + for app in sapl_appconfs: + for model in app.get_models(): + fields = model._meta.local_fields + for field in fields: if isinstance(field, (CharField, TextField)): msg = 'Model = %s || Field = %s - %s - %s' % ( model.__name__, field.attname, type(field).__name__, field.null) - raise AssertionError(msg) + assert not field.null, msg def test_str_sanity(): # this simply a sanity check # __str__ semantics is not considered and should be tested separetely - sapl_appconfs = [apps.get_app_config(n) for n in SAPL_APPS] for app in sapl_appconfs: for model in app.get_models(): obj = mommy.prepare(model) From aa5d3bace65fd76529ef8bf11322c9186abd80d4 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Mon, 4 Apr 2016 14:04:24 -0300 Subject: [PATCH 24/27] Desliga teste de cadastro de parlamentar (temp) --- parlamentares/test_parlamentares.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/parlamentares/test_parlamentares.py b/parlamentares/test_parlamentares.py index f7a04fba7..4272998e3 100644 --- a/parlamentares/test_parlamentares.py +++ b/parlamentares/test_parlamentares.py @@ -6,8 +6,9 @@ from .models import (Dependente, Filiacao, Legislatura, Mandato, Parlamentar, Partido, TipoDependente) +# vamos refazer a funcionalidade adicionando os campos ogrigatórios de mandato @pytest.mark.django_db(transaction=False) -def test_cadastro_parlamentar(client): +def TODO_DESLIGADO_RELIGAR_test_cadastro_parlamentar(client): mommy.make(Legislatura, pk=5) response = client.get(reverse('parlamentares_cadastro', kwargs={'pk': 5})) From 70916514b35b9537e289c20c8bf142939b95aa6c Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Mon, 4 Apr 2016 14:10:26 -0300 Subject: [PATCH 25/27] Adiciona migrations esquecidas --- materia/migrations/0027_auto_20160404_1409.py | 27 ++++++++ .../migrations/0016_auto_20160404_1409.py | 22 ++++++ sapl/utils.py | 68 ++++++++++--------- sessao/migrations/0016_auto_20160404_1409.py | 27 ++++++++ 4 files changed, 111 insertions(+), 33 deletions(-) create mode 100644 materia/migrations/0027_auto_20160404_1409.py create mode 100644 parlamentares/migrations/0016_auto_20160404_1409.py create mode 100644 sessao/migrations/0016_auto_20160404_1409.py diff --git a/materia/migrations/0027_auto_20160404_1409.py b/materia/migrations/0027_auto_20160404_1409.py new file mode 100644 index 000000000..c15f9015f --- /dev/null +++ b/materia/migrations/0027_auto_20160404_1409.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-04-04 17:09 +from __future__ import unicode_literals + +from django.db import migrations, models +import materia.models +import sapl.utils + + +class Migration(migrations.Migration): + + dependencies = [ + ('materia', '0026_auto_20160322_1514'), + ] + + operations = [ + migrations.AlterField( + model_name='materialegislativa', + name='texto_original', + field=models.FileField(blank=True, null=True, upload_to=materia.models.texto_upload_path, validators=[sapl.utils.restringe_tipos_de_arquivo_txt], verbose_name='Texto Original (PDF)'), + ), + migrations.AlterField( + model_name='proposicao', + name='texto_original', + field=models.FileField(blank=True, null=True, upload_to=materia.models.texto_upload_path, validators=[sapl.utils.restringe_tipos_de_arquivo_txt], verbose_name='Texto Original (PDF)'), + ), + ] diff --git a/parlamentares/migrations/0016_auto_20160404_1409.py b/parlamentares/migrations/0016_auto_20160404_1409.py new file mode 100644 index 000000000..c467f6c82 --- /dev/null +++ b/parlamentares/migrations/0016_auto_20160404_1409.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-04-04 17:09 +from __future__ import unicode_literals + +from django.db import migrations, models +import parlamentares.models +import sapl.utils + + +class Migration(migrations.Migration): + + dependencies = [ + ('parlamentares', '0015_auto_20160322_1401'), + ] + + operations = [ + migrations.AlterField( + model_name='parlamentar', + name='fotografia', + field=models.ImageField(blank=True, null=True, upload_to=parlamentares.models.foto_upload_path, validators=[sapl.utils.restringe_tipos_de_arquivo_img], verbose_name='Fotografia'), + ), + ] diff --git a/sapl/utils.py b/sapl/utils.py index 71f640578..6f7004c67 100644 --- a/sapl/utils.py +++ b/sapl/utils.py @@ -94,35 +94,35 @@ def listify(function): return f UF = [ - ('AC', 'Acre'), - ('AL', 'Alagoas'), - ('AP', 'Amapá'), - ('AM', 'Amazonas'), - ('BA', 'Bahia'), - ('CE', 'Ceará'), - ('DF', 'Distrito Federal'), - ('ES', 'Espírito Santo'), - ('GO', 'Goiás'), - ('MA', 'Maranhão'), - ('MT', 'Mato Grosso'), - ('MS', 'Mato Grosso do Sul'), - ('MG', 'Minas Gerais'), - ('PR', 'Paraná'), - ('PB', 'Paraíba'), - ('PA', 'Pará'), - ('PE', 'Pernambuco'), - ('PI', 'Piauí'), - ('RJ', 'Rio de Janeiro'), - ('RN', 'Rio Grande do Norte'), - ('RS', 'Rio Grande do Sul'), - ('RO', 'Rondônia'), - ('RR', 'Roraima'), - ('SC', 'Santa Catarina'), - ('SE', 'Sergipe'), - ('SP', 'São Paulo'), - ('TO', 'Tocantins'), - ('EX', 'Exterior'), - ] + ('AC', 'Acre'), + ('AL', 'Alagoas'), + ('AP', 'Amapá'), + ('AM', 'Amazonas'), + ('BA', 'Bahia'), + ('CE', 'Ceará'), + ('DF', 'Distrito Federal'), + ('ES', 'Espírito Santo'), + ('GO', 'Goiás'), + ('MA', 'Maranhão'), + ('MT', 'Mato Grosso'), + ('MS', 'Mato Grosso do Sul'), + ('MG', 'Minas Gerais'), + ('PR', 'Paraná'), + ('PB', 'Paraíba'), + ('PA', 'Pará'), + ('PE', 'Pernambuco'), + ('PI', 'Piauí'), + ('RJ', 'Rio de Janeiro'), + ('RN', 'Rio Grande do Norte'), + ('RS', 'Rio Grande do Sul'), + ('RO', 'Rondônia'), + ('RR', 'Roraima'), + ('SC', 'Santa Catarina'), + ('SE', 'Sergipe'), + ('SP', 'São Paulo'), + ('TO', 'Tocantins'), + ('EX', 'Exterior'), +] RANGE_ANOS = [(year, year) for year in range(date.today().year, 1889, -1)] @@ -146,7 +146,7 @@ TIPOS_TEXTO_PERMITIDOS = ( 'application/xml', 'text/xml', 'text/html', - ) +) TIPOS_IMG_PERMITIDOS = ( 'image/jpeg', @@ -169,16 +169,18 @@ TIPOS_IMG_PERMITIDOS = ( ) -def fabrica_validador_de_tipos_de_arquivo(lista): +def fabrica_validador_de_tipos_de_arquivo(lista, nome): def restringe_tipos_de_arquivo(value): mime = magic.from_buffer(value.read(), mime=True) mime = mime.decode() if mime not in lista: raise ValidationError(_('Tipo de arquivo não suportado')) + # o nome é importante para as migrations + restringe_tipos_de_arquivo.__name__ = nome return restringe_tipos_de_arquivo restringe_tipos_de_arquivo_txt = fabrica_validador_de_tipos_de_arquivo( - TIPOS_TEXTO_PERMITIDOS) + TIPOS_TEXTO_PERMITIDOS, 'restringe_tipos_de_arquivo_txt') restringe_tipos_de_arquivo_img = fabrica_validador_de_tipos_de_arquivo( - TIPOS_IMG_PERMITIDOS) + TIPOS_IMG_PERMITIDOS, 'restringe_tipos_de_arquivo_img') diff --git a/sessao/migrations/0016_auto_20160404_1409.py b/sessao/migrations/0016_auto_20160404_1409.py new file mode 100644 index 000000000..b436d098f --- /dev/null +++ b/sessao/migrations/0016_auto_20160404_1409.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-04-04 17:09 +from __future__ import unicode_literals + +from django.db import migrations, models +import sapl.utils +import sessao.models + + +class Migration(migrations.Migration): + + dependencies = [ + ('sessao', '0015_auto_20160307_0918'), + ] + + operations = [ + migrations.AlterField( + model_name='sessaoplenaria', + name='upload_ata', + field=models.FileField(blank=True, null=True, upload_to=sessao.models.ata_upload_path, validators=[sapl.utils.restringe_tipos_de_arquivo_txt], verbose_name='Ata da Sessão'), + ), + migrations.AlterField( + model_name='sessaoplenaria', + name='upload_pauta', + field=models.FileField(blank=True, null=True, upload_to=sessao.models.pauta_upload_path, validators=[sapl.utils.restringe_tipos_de_arquivo_txt], verbose_name='Pauta da Sessão'), + ), + ] From cf10657649870dce28620a35afd1b86d2a56bc50 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Mon, 4 Apr 2016 14:11:58 -0300 Subject: [PATCH 26/27] Remove null=True de TextField --- .../migrations/0045_auto_20160404_1411.py | 21 +++++++++++++++++++ compilacao/models.py | 3 +-- 2 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 compilacao/migrations/0045_auto_20160404_1411.py diff --git a/compilacao/migrations/0045_auto_20160404_1411.py b/compilacao/migrations/0045_auto_20160404_1411.py new file mode 100644 index 000000000..a934e8bf0 --- /dev/null +++ b/compilacao/migrations/0045_auto_20160404_1411.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-04-04 17:11 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('compilacao', '0044_auto_20160307_0918'), + ] + + operations = [ + migrations.AlterField( + model_name='textoarticulado', + name='observacao', + field=models.TextField(blank=True, default='', verbose_name='Observação'), + preserve_default=False, + ), + ] diff --git a/compilacao/models.py b/compilacao/models.py index c7e9f7f05..8ce953a98 100644 --- a/compilacao/models.py +++ b/compilacao/models.py @@ -90,8 +90,7 @@ PARTICIPACAO_SOCIAL_CHOICES = [ class TextoArticulado(TimestampedMixin): data = models.DateField(blank=True, null=True, verbose_name=_('Data')) ementa = models.TextField(verbose_name=_('Ementa')) - observacao = models.TextField( - blank=True, null=True, verbose_name=_('Observação')) + observacao = models.TextField(blank=True, verbose_name=_('Observação')) numero = models.PositiveIntegerField(verbose_name=_('Número')) ano = models.PositiveSmallIntegerField(verbose_name=_('Ano')) tipo_ta = models.ForeignKey( From d1217fce38046326333110b105536011a2491bb7 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Mon, 4 Apr 2016 14:13:36 -0300 Subject: [PATCH 27/27] Conserta imports --- sapl/test_general.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sapl/test_general.py b/sapl/test_general.py index dac87ffa1..53465b193 100644 --- a/sapl/test_general.py +++ b/sapl/test_general.py @@ -1,6 +1,6 @@ import pytest -from django.db.models import CharField, TextField from django.apps import apps +from django.db.models import CharField, TextField from model_mommy import mommy from .settings import SAPL_APPS