diff --git a/sapl/base/migrations/0019_auto_20160928_1951.py b/sapl/base/migrations/0019_auto_20160928_1951.py
new file mode 100644
index 000000000..9c61f7062
--- /dev/null
+++ b/sapl/base/migrations/0019_auto_20160928_1951.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-09-28 22:51
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('base', '0018_auto_20160919_1333'),
+ ]
+
+ operations = [
+ migrations.AlterModelOptions(
+ name='appconfig',
+ options={'permissions': (('menu_sistemas', 'Renderizar Menu Sistemas'), ('view_tabelas_auxiliares', 'Visualizar Tabelas Auxiliares')), 'verbose_name': 'Configurações da Aplicação', 'verbose_name_plural': 'Configurações da Aplicação'},
+ ),
+ ]
diff --git a/sapl/base/models.py b/sapl/base/models.py
index 86a685ef4..12e840fda 100644
--- a/sapl/base/models.py
+++ b/sapl/base/models.py
@@ -1,10 +1,21 @@
+from builtins import LookupError
+
+from django.apps import apps
+from django.conf.urls import include, url
+from django.contrib.auth.management import _get_all_permissions
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
+from django.core import exceptions
from django.db import models
+from django.db import models, router
+from django.db.utils import DEFAULT_DB_ALIAS
+from django.utils.translation import string_concat
from django.utils.translation import ugettext_lazy as _
+from rest_framework import permissions
from sapl.utils import UF, YES_NO_CHOICES
+
TIPO_DOCUMENTO_ADMINISTRATIVO = (('O', _('Ostensivo')),
('R', _('Restritivo')))
@@ -94,7 +105,107 @@ class AppConfig(models.Model):
class Meta:
verbose_name = _('Configurações da Aplicação')
verbose_name_plural = _('Configurações da Aplicação')
+ permissions = (
+ ('menu_sistemas', _('Renderizar Menu Sistemas')),
+ ('view_tabelas_auxiliares', _('Visualizar Tabelas Auxiliares')),
+ )
def __str__(self):
return _('Configurações da Aplicação - %(id)s') % {
'id': self.id}
+
+
+def create_proxy_permissions(
+ app_config, verbosity=2, interactive=True,
+ using=DEFAULT_DB_ALIAS, **kwargs):
+ if not app_config.models_module:
+ return
+
+ # print(app_config)
+
+ try:
+ Permission = apps.get_model('auth', 'Permission')
+ except LookupError:
+ return
+
+ if not router.allow_migrate_model(using, Permission):
+ return
+
+ from django.contrib.contenttypes.models import ContentType
+
+ permission_name_max_length = Permission._meta.get_field('name').max_length
+
+ # This will hold the permissions we're looking for as
+ # (content_type, (codename, name))
+ searched_perms = list()
+ # The codenames and ctypes that should exist.
+ ctypes = set()
+ for klass in list(app_config.get_models()):
+ opts = klass._meta
+ permissions = (
+ ("list_" + opts.model_name,
+ string_concat(
+ _('Visualizaçao da lista de'), ' ',
+ opts.verbose_name_plural)),
+ ("detail_" + opts.model_name,
+ string_concat(
+ _('Visualização dos detalhes de'), ' ',
+ opts.verbose_name_plural)),
+ )
+ opts.permissions = tuple(
+ set(list(permissions) + list(opts.permissions)))
+
+ if opts.proxy:
+ # Force looking up the content types in the current database
+ # before creating foreign keys to them.
+ app_label, model = opts.app_label, opts.model_name
+
+ try:
+ ctype = ContentType.objects.db_manager(
+ using).get_by_natural_key(app_label, model)
+ except:
+ ctype = ContentType.objects.db_manager(
+ using).create(app_label=app_label, model=model)
+ else:
+ ctype = ContentType.objects.db_manager(using).get_for_model(klass)
+
+ ctypes.add(ctype)
+ for perm in _get_all_permissions(klass._meta, ctype):
+ searched_perms.append((ctype, perm))
+
+ # Find all the Permissions that have a content_type for a model we're
+ # looking for. We don't need to check for codenames since we already have
+ # a list of the ones we're going to create.
+ all_perms = set(Permission.objects.using(using).filter(
+ content_type__in=ctypes,
+ ).values_list(
+ "content_type", "codename"
+ ))
+
+ perms = [
+ Permission(codename=codename, name=name, content_type=ct)
+ for ct, (codename, name) in searched_perms
+ if (ct.pk, codename) not in all_perms
+ ]
+ # Validate the permissions before bulk_creation to avoid cryptic database
+ # error when the name is longer than 255 characters
+ for perm in perms:
+ if len(perm.name) > permission_name_max_length:
+ raise exceptions.ValidationError(
+ 'The permission name %s of %s.%s '
+ 'is longer than %s characters' % (
+ perm.name,
+ perm.content_type.app_label,
+ perm.content_type.model,
+ permission_name_max_length,
+ )
+ )
+ Permission.objects.using(using).bulk_create(perms)
+ if verbosity >= 2:
+ for perm in perms:
+ print("Adding permission '%s'" % perm)
+
+
+models.signals.post_migrate.connect(
+ receiver=create_proxy_permissions,
+ dispatch_uid="django.contrib.auth.management.create_permissions")
diff --git a/sapl/base/templatetags/common_tags.py b/sapl/base/templatetags/common_tags.py
index 30db1a92f..ec21ce48b 100644
--- a/sapl/base/templatetags/common_tags.py
+++ b/sapl/base/templatetags/common_tags.py
@@ -126,3 +126,14 @@ def get_config_not_exists(user):
return True
else:
return False
+
+@register.filter
+def str2intabs(value):
+ if not isinstance(value, str):
+ return ''
+ try:
+ v = int(value)
+ v = abs(v)
+ return v
+ except:
+ return ''
diff --git a/sapl/base/urls.py b/sapl/base/urls.py
index 784649cfd..22691759d 100644
--- a/sapl/base/urls.py
+++ b/sapl/base/urls.py
@@ -1,5 +1,6 @@
from django.conf.urls import include, url
from django.contrib.auth import views
+from django.contrib.auth.decorators import permission_required
from django.views.generic.base import TemplateView
from .apps import AppConfig
@@ -11,11 +12,14 @@ from .views import (AppConfigCrud, CasaLegislativaCrud, HelpView,
RelatorioMateriasTramitacaoView,
RelatorioPresencaSessaoView)
+
app_name = AppConfig.name
urlpatterns = [
- url(r'^sistema/', TemplateView.as_view(template_name='sistema.html')),
+ url(r'^sistema/', permission_required('base.view_tabelas_auxiliares')
+ (TemplateView.as_view(template_name='sistema.html'))),
+
url(r'^ajuda/', TemplateView.as_view(template_name='ajuda.html')),
url(r'^relatorios/', TemplateView.as_view(
template_name='base/relatorios_list.html')),
diff --git a/sapl/base/views.py b/sapl/base/views.py
index 4cb3a5c52..2e48efc3a 100644
--- a/sapl/base/views.py
+++ b/sapl/base/views.py
@@ -1,4 +1,5 @@
-from django.contrib.auth.mixins import PermissionRequiredMixin
+
+from braces.views import PermissionRequiredMixin
from django.core.urlresolvers import reverse
from django.db.models import Count, Q
from django.http import HttpResponseRedirect
@@ -229,16 +230,16 @@ class CasaLegislativaCrud(Crud):
model = CasaLegislativa
help_path = ''
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
list_field_names = ['codigo', 'nome', 'sigla']
def has_permission(self):
return permissao_tb_aux(self)
- class CreateView(PermissionRequiredMixin, CrudCreateView):
+ class CreateView(CrudCreateView):
form_class = CasaLegislativaForm
- class UpdateView(PermissionRequiredMixin, CrudUpdateView):
+ class UpdateView(CrudUpdateView):
form_class = CasaLegislativaForm
class DetailView(CrudDetailView):
@@ -269,7 +270,7 @@ class AppConfigCrud(Crud):
model = AppConfig
help_path = ''
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
list_field_names = ['documentos_administrativos',
'sequencia_numeracao',
'painel_aberto']
@@ -277,7 +278,7 @@ class AppConfigCrud(Crud):
def has_permission(self):
return permissao_tb_aux(self)
- class CreateView(PermissionRequiredMixin, CrudCreateView):
+ class CreateView(CrudCreateView):
form_class = ConfiguracoesAppForm
def get(self, request, *args, **kwargs):
@@ -291,5 +292,5 @@ class AppConfigCrud(Crud):
return super(BaseCreateView, self).get(
request, *args, **kwargs)
- class UpdateView(PermissionRequiredMixin, CrudUpdateView):
+ class UpdateView(CrudUpdateView):
form_class = ConfiguracoesAppForm
diff --git a/sapl/comissoes/migrations/0008_auto_20160929_1611.py b/sapl/comissoes/migrations/0008_auto_20160929_1611.py
new file mode 100644
index 000000000..5e90c95b4
--- /dev/null
+++ b/sapl/comissoes/migrations/0008_auto_20160929_1611.py
@@ -0,0 +1,21 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.7 on 2016-09-29 19:11
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('comissoes', '0007_merge'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='participacao',
+ name='composicao',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='participacao_set', to='comissoes.Composicao'),
+ ),
+ ]
diff --git a/sapl/comissoes/models.py b/sapl/comissoes/models.py
index 579b95f2a..60aee6368 100644
--- a/sapl/comissoes/models.py
+++ b/sapl/comissoes/models.py
@@ -131,7 +131,7 @@ class Composicao(models.Model): # IGNORE
class Participacao(models.Model): # ComposicaoComissao
- composicao = models.ForeignKey(Composicao)
+ composicao = models.ForeignKey(Composicao, related_name='participacao_set')
parlamentar = models.ForeignKey(Parlamentar)
cargo = models.ForeignKey(CargoComissao)
titular = models.BooleanField(verbose_name=_('Titular'))
diff --git a/sapl/comissoes/views.py b/sapl/comissoes/views.py
index e472a69cc..8207ac290 100644
--- a/sapl/comissoes/views.py
+++ b/sapl/comissoes/views.py
@@ -1,10 +1,11 @@
+from django.contrib.auth.decorators import permission_required
from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.urlresolvers import reverse
from django.views.generic import ListView
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
- CrudDeleteView, CrudListView, CrudUpdateView)
-from sapl.crud.masterdetail import MasterDetailCrud
+ CrudDeleteView, CrudListView, CrudUpdateView,
+ MasterDetailCrud, CrudAux)
from sapl.materia.models import MateriaLegislativa, Tramitacao
from sapl.utils import permissao_tb_aux, permissoes_comissoes
@@ -18,130 +19,52 @@ def pegar_url_composicao(pk):
url = reverse('sapl.comissoes:composicao_detail', kwargs={'pk': comp_pk})
return url
+CargoCrud = CrudAux.build(CargoComissao, 'cargo_comissao')
+PeriodoComposicaoCrud = CrudAux.build(Periodo, 'periodo_composicao_comissao')
-class CargoCrud(Crud):
- model = CargoComissao
- help_path = 'cargo_comissao'
-
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
- list_field_names = ['nome', 'unico']
-
- def has_permission(self):
- return permissao_tb_aux(self)
-
-
-class PeriodoComposicaoCrud(Crud):
- model = Periodo
- help_path = 'periodo_composicao_comissao'
-
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
- list_field_names = ['data_inicio', 'data_fim']
-
- def has_permission(self):
- return permissao_tb_aux(self)
-
-
-class TipoComissaoCrud(Crud):
- model = TipoComissao
- help_path = 'tipo_comissao'
-
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
- list_field_names = ['sigla', 'nome', 'natureza',
- 'dispositivo_regimental']
-
- def has_permission(self):
- return permissao_tb_aux(self)
+TipoComissaoCrud = CrudAux.build(
+ TipoComissao, 'tipo_comissao', list_field_names=[
+ 'sigla', 'nome', 'natureza', 'dispositivo_regimental'])
class ParticipacaoCrud(MasterDetailCrud):
model = Participacao
- parent_field = 'composicao'
+ parent_field = 'composicao__comissao'
help_path = ''
- class DetailView(MasterDetailCrud.DetailView):
- def get(self, request, *args, **kwargs):
- self.object = self.get_object()
- context = self.get_context_data(object=self.object)
- context['root_pk'] = self.object.composicao.comissao.pk
- return self.render_to_response(context)
-
- class CreateView(MasterDetailCrud.CreateView):
-
- def get_success_url(self):
- return reverse(
- 'sapl.comissoes:composicao_detail',
- kwargs={'pk': self.kwargs['pk']}
- )
-
- def cancel_url(self):
- return reverse(
- 'sapl.comissoes:composicao_detail',
- kwargs={'pk': self.kwargs['pk']}
- )
-
- class UpdateView(MasterDetailCrud.UpdateView):
-
- def get_success_url(self):
- return pegar_url_composicao(self.kwargs['pk'])
-
- def cancel_url(self):
- return pegar_url_composicao(self.kwargs['pk'])
-
- class DeleteView(MasterDetailCrud.DeleteView):
-
- def get_success_url(self):
- return pegar_url_composicao(self.kwargs['pk'])
-
- def cancel_url(self):
- return pegar_url_composicao(self.kwargs['pk'])
-
- class BaseMixin(PermissionRequiredMixin, MasterDetailCrud.BaseMixin):
- permission_required = permissoes_comissoes()
+ class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['composicao', 'parlamentar', 'cargo']
+ class DetailView(MasterDetailCrud.DetailView):
+ permission_required = []
+
class ComposicaoCrud(MasterDetailCrud):
model = Composicao
parent_field = 'comissao'
help_path = ''
+ model_set = 'participacao_set'
- class DetailView(MasterDetailCrud.DetailView):
-
- def get(self, request, *args, **kwargs):
- self.object = self.get_object()
- context = self.get_context_data(object=self.object)
- composicao = Composicao.objects.get(id=self.kwargs['pk'])
- context['participacoes'] = composicao.participacao_set.all()
- return self.render_to_response(context)
-
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
- permission_required = permissoes_comissoes()
+ class ListView(MasterDetailCrud.ListView):
+ permission_required = []
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
- permission_required = permissoes_comissoes()
-
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
- permission_required = permissoes_comissoes()
+ class DetailView(MasterDetailCrud.DetailView):
+ permission_required = []
class ComissaoCrud(Crud):
model = Comissao
help_path = 'modulo_comissoes'
- class CreateView(PermissionRequiredMixin, CrudCreateView):
- permission_required = permissoes_comissoes()
-
- class UpdateView(PermissionRequiredMixin, CrudUpdateView):
- permission_required = permissoes_comissoes()
-
- class DeleteView(PermissionRequiredMixin, CrudDeleteView):
- permission_required = permissoes_comissoes()
+ class BaseMixin(Crud.BaseMixin):
+ list_field_names = ['nome', 'sigla', 'tipo', 'data_criacao', 'ativa']
+ initial_order = '-ativa', 'sigla'
- class ListView(CrudListView):
- ordering = ['-ativa', 'sigla']
+ class ListView(Crud.ListView):
+ permission_required = []
- class BaseMixin(CrudBaseMixin):
- list_field_names = ['nome', 'sigla', 'tipo', 'data_criacao', 'ativa']
+ class DetailView(Crud.DetailView):
+ permission_required = []
class MateriasTramitacaoListView(ListView):
diff --git a/sapl/crispy_layout_mixin.py b/sapl/crispy_layout_mixin.py
index 6ac4a2e22..89dd2da8e 100644
--- a/sapl/crispy_layout_mixin.py
+++ b/sapl/crispy_layout_mixin.py
@@ -1,12 +1,12 @@
from math import ceil
-import rtyaml
from crispy_forms.bootstrap import FormActions
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Div, Fieldset, Layout, Submit
from django import template
from django.utils import formats
from django.utils.translation import ugettext as _
+import rtyaml
def heads_and_tails(list_of_lists):
@@ -97,10 +97,25 @@ class CrispyLayoutFormMixin:
else:
return self.model.__name__
+ @property
+ def layout_key_set(self):
+ if hasattr(super(CrispyLayoutFormMixin, self), 'layout_key_set'):
+ return super(CrispyLayoutFormMixin, self).layout_key_set
+ else:
+ obj = self.crud if hasattr(self, 'crud') else self
+ return getattr(obj.model,
+ obj.model_set).field.model.__name__
+
def get_layout(self):
yaml_layout = '%s/layouts.yaml' % self.model._meta.app_config.label
return read_layout_from_yaml(yaml_layout, self.layout_key)
+ def get_layout_set(self):
+ obj = self.crud if hasattr(self, 'crud') else self
+ yaml_layout = '%s/layouts.yaml' % getattr(
+ obj.model, obj.model_set).field.model._meta.app_config.label
+ return read_layout_from_yaml(yaml_layout, self.layout_key_set)
+
@property
def fields(self):
if hasattr(self, 'form_class') and self.form_class:
@@ -132,6 +147,16 @@ class CrispyLayoutFormMixin:
rows = self.get_layout()[0][1:]
return [fieldname for row in rows for fieldname, __ in row]
+ @property
+ def list_field_names_set(self):
+ '''The list of field names to display on table
+
+ This base implementation returns the field names
+ in the first fieldset of the layout.
+ '''
+ rows = self.get_layout_set()[0][1:]
+ return [fieldname for row in rows for fieldname, __ in row]
+
def get_column(self, fieldname, span):
obj = self.get_object()
verbose_name, text = get_field_display(obj, fieldname)
diff --git a/sapl/crud/base.py b/sapl/crud/base.py
index 289bd21e1..d480684b6 100644
--- a/sapl/crud/base.py
+++ b/sapl/crud/base.py
@@ -1,26 +1,52 @@
+import logging
+
from braces.views import FormMessagesMixin
+from compressor.utils.decorators import cached_property
+from crispy_forms.bootstrap import FieldWithButtons, StrictButton
+from crispy_forms.helper import FormHelper
+from crispy_forms.layout import Layout, Field
+from django import forms
+from django.apps import apps
from django.conf.urls import url
+from django.contrib.auth.management import _get_all_permissions
+from django.contrib.auth.mixins import PermissionRequiredMixin
+from django.core import exceptions
from django.core.urlresolvers import reverse
+from django.db import models, router
+from django.db.utils import DEFAULT_DB_ALIAS
+from django.http.response import Http404
+from django.shortcuts import redirect
from django.utils.decorators import classonlymethod
-from django.utils.translation import ugettext_lazy as _
+from django.utils.encoding import force_text
+from django.utils.translation import ugettext_lazy as _, string_concat
from django.views.generic import (CreateView, DeleteView, DetailView, ListView,
UpdateView)
+from django.views.generic.base import ContextMixin
+from django.views.generic.list import MultipleObjectMixin
from sapl.crispy_layout_mixin import CrispyLayoutFormMixin, get_field_display
+from sapl.utils import normalize
+
+
+logger = logging.getLogger(__name__)
-LIST, CREATE, DETAIL, UPDATE, DELETE = \
+ACTION_LIST, ACTION_CREATE, ACTION_DETAIL, ACTION_UPDATE, ACTION_DELETE = \
'list', 'create', 'detail', 'update', 'delete'
+# RP - Radical das permissões para "..."
+RP_LIST, RP_DETAIL, RP_ADD, RP_CHANGE, RP_DELETE =\
+ '.list_', '.detail_', '.add_', '.change_', '.delete_',
+
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 = {ACTION_CREATE: (_('Registro criado com sucesso!'),
+ _('O registro não foi criado.')),
+ ACTION_UPDATE: (_('Registro alterado com sucesso!'),
+ _('Suas alterações não foram salvas.')),
+ ACTION_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()}
@@ -55,37 +81,228 @@ def make_pagination(index, num_pages):
head = from_to(1, PAGINATION_LENGTH - len(tail) - 1)
return head + [None] + tail
+"""
+variáveis do crud:
+ container_field
+ container_field_set
+ is_m2m
+ model
+ model_set
+ form_search_class -> depende de o model relativo implementar SearchMixin
+ list_field_names
+ list_field_names_set -> lista reversa em details
+ permission_required -> este atributo ser vazio não nulo torna a view publ
+ layout_key_set
+ layout_key
+ parent_field = parentesco reverso separado por '__'
+ initial_order = deve ser um elemento de list_field_names
+ FIXME: as setas indicativas de ordem em crud/list.html
+ não está se comportando como esperado para initial_order descrescente
+"""
+
+
+class SearchMixin(models.Model):
+
+ search = models.TextField(blank=True, default='')
+
+ class Meta:
+ abstract = True
+
+ def save(self, force_insert=False, force_update=False, using=None,
+ update_fields=None, auto_update_search=True):
+
+ if auto_update_search and hasattr(self, 'fields_search'):
+ search = ''
+ for str_field in self.fields_search:
+ fields = str_field.split('__')
+ if len(fields) == 1:
+ try:
+ search += str(getattr(self, str_field)) + ' '
+ except:
+ pass
+ else:
+ _self = self
+ for field in fields:
+ _self = getattr(_self, field)
+ search += str(_self) + ' '
+ self.search = search
+ self.search = normalize(self.search)
+
+ return super(SearchMixin, self).save(
+ force_insert=force_insert, force_update=force_update,
+ using=using, update_fields=update_fields)
+
+
+class ListWithSearchForm(forms.Form):
+ q = forms.CharField(required=False, label='',
+ widget=forms.TextInput(
+ attrs={'type': 'search'}))
+
+ o = forms.CharField(required=False, label='',
+ widget=forms.HiddenInput())
+
+ class Meta:
+ fields = ['q', 'o']
+
+ def __init__(self, *args, **kwargs):
+ super(ListWithSearchForm, self).__init__(*args, **kwargs)
+
+ self.helper = FormHelper()
+ self.form_class = 'form-inline'
+ self.helper.form_method = 'GET'
+ self.helper.layout = Layout(
+ Field('o'),
+ FieldWithButtons(
+ Field('q',
+ placeholder=_('Filtrar Lista'),
+ css_class='input-lg'),
+ StrictButton(
+ _('Filtrar'), css_class='btn-default btn-lg',
+ type='submit'))
+ )
+
+
+class PermissionRequiredContainerCrudMixin(PermissionRequiredMixin):
+
+ def has_permission(self):
+ perms = self.get_permission_required()
+ # Torna a view pública se não possuir o atributo permission_required
+ return self.request.user.has_perms(perms) if len(perms) else True
+
+ def dispatch(self, request, *args, **kwargs):
+ if not self.has_permission():
+ return self.handle_no_permission()
+
+ if 'pk' in kwargs:
+ params = {'pk': kwargs['pk']}
+
+ if self.container_field:
+ params[self.container_field] = request.user.pk
+
+ if not self.model.objects.filter(**params).exists():
+ raise Http404()
+
+ return super(PermissionRequiredMixin, self).dispatch(
+ request, *args, **kwargs)
+
+ @cached_property
+ def container_field(self):
+ if hasattr(self, 'crud') and not hasattr(self.crud, 'container_field'):
+ self.crud.container_field = ''
+ if hasattr(self, 'crud'):
+ return self.crud.container_field
+
+ @cached_property
+ def container_field_set(self):
+ if hasattr(self, 'crud') and\
+ not hasattr(self.crud, 'container_field_set'):
+ self.crud.container_field_set = ''
+ if hasattr(self, 'crud'):
+ return self.crud.container_field_set
+
+ @cached_property
+ def is_contained(self):
+ return self.container_field_set or self.container_field
+
class CrudBaseMixin(CrispyLayoutFormMixin):
+ def __init__(self, **kwargs):
+ obj = self.crud if hasattr(self, 'crud') else self
+ self.app_label = obj.model._meta.app_label
+ self.model_name = obj.model._meta.model_name
+
+ if hasattr(obj, 'model_set') and obj.model_set:
+ self.app_label_set = getattr(
+ obj.model, obj.model_set).field.model._meta.app_label
+ self.model_name_set = getattr(
+ obj.model, obj.model_set).field.model._meta.model_name
+
+ if hasattr(self, 'permission_required') and\
+ self.permission_required:
+ self.permission_required = tuple((
+ self.permission(pr) for pr in self.permission_required))
+
@classmethod
def url_name(cls, suffix):
return '%s_%s' % (cls.model._meta.model_name, suffix)
+ def url_name_set(self, suffix):
+ obj = self.crud if hasattr(self, 'crud') else self
+ return '%s_%s' % (getattr(
+ obj.model, obj.model_set).field.model._meta.model_name, suffix)
+
+ def permission(self, rad):
+ return '%s%s%s' % (self.app_label if rad.endswith('_') else '',
+ rad,
+ self.model_name if rad.endswith('_') else '')
+
+ def permission_set(self, rad):
+ return '%s%s%s' % (self.app_label_set if rad.endswith('_') else '',
+ rad,
+ self.model_name_set if rad.endswith('_') else '')
+
def resolve_url(self, suffix, args=None):
namespace = self.model._meta.app_config.name
return reverse('%s:%s' % (namespace, self.url_name(suffix)),
args=args)
+ def resolve_url_set(self, suffix, args=None):
+ obj = self.crud if hasattr(self, 'crud') else self
+ namespace = getattr(
+ obj.model, obj.model_set).field.model._meta.app_config.name
+ return reverse('%s:%s' % (namespace, self.url_name_set(suffix)),
+ args=args)
+
@property
def list_url(self):
- return self.resolve_url(LIST)
+ obj = self.crud if hasattr(self, 'crud') else self
+ if not obj.ListView.permission_required:
+ return self.resolve_url(ACTION_LIST)
+ else:
+ return self.resolve_url(
+ ACTION_LIST) if self.request.user.has_perm(
+ self.permission(RP_LIST)) else ''
@property
def create_url(self):
- return self.resolve_url(CREATE)
+ obj = self.crud if hasattr(self, 'crud') else self
+ if not obj.CreateView.permission_required:
+ return self.resolve_url(ACTION_CREATE)
+ else:
+ return self.resolve_url(
+ ACTION_CREATE) if self.request.user.has_perm(
+ self.permission(RP_ADD)) else ''
@property
def detail_url(self):
- return self.resolve_url(DETAIL, args=(self.object.id,))
+ obj = self.crud if hasattr(self, 'crud') else self
+ if not obj.DetailView.permission_required:
+ return self.resolve_url(ACTION_DETAIL, args=(self.object.id,))
+ else:
+ return self.resolve_url(ACTION_DETAIL, args=(self.object.id,))\
+ if self.request.user.has_perm(
+ self.permission(RP_DETAIL)) else ''
@property
def update_url(self):
- return self.resolve_url(UPDATE, args=(self.object.id,))
+ obj = self.crud if hasattr(self, 'crud') else self
+ if not obj.UpdateView.permission_required:
+ return self.resolve_url(ACTION_UPDATE, args=(self.object.id,))
+ else:
+ return self.resolve_url(ACTION_UPDATE, args=(self.object.id,))\
+ if self.request.user.has_perm(
+ self.permission(RP_CHANGE)) else ''
@property
def delete_url(self):
- return self.resolve_url(DELETE, args=(self.object.id,))
+ obj = self.crud if hasattr(self, 'crud') else self
+ if not obj.DeleteView.permission_required:
+ return self.resolve_url(ACTION_DELETE)
+ else:
+ return self.resolve_url(ACTION_DELETE, args=(self.object.id,))\
+ if self.request.user.has_perm(
+ self.permission(RP_DELETE)) else ''
def get_template_names(self):
names = super(CrudBaseMixin, self).get_template_names()
@@ -93,6 +310,11 @@ class CrudBaseMixin(CrispyLayoutFormMixin):
self.template_name_suffix.lstrip('_'))
return names
+ @property
+ def verbose_name_set(self):
+ obj = self.crud if hasattr(self, 'crud') else self
+ return getattr(obj.model, obj.model_set).field.model._meta.verbose_name
+
@property
def verbose_name(self):
return self.model._meta.verbose_name
@@ -102,12 +324,12 @@ class CrudBaseMixin(CrispyLayoutFormMixin):
return self.model._meta.verbose_name_plural
-class CrudListView(ListView):
+class CrudListView(PermissionRequiredContainerCrudMixin, ListView):
+ permission_required = (RP_LIST, )
@classmethod
def get_url_regex(cls):
return r'^$'
-
paginate_by = 10
no_entries_msg = _('Nenhum registro encontrado.')
@@ -115,18 +337,73 @@ class CrudListView(ListView):
return [self._as_row(obj) for obj in object_list]
def get_headers(self):
- return [self.model._meta.get_field(fieldname).verbose_name
- for fieldname in self.list_field_names]
+ """
+ Transforma o headers de fields de list_field_names
+ para junção de fields via tuplas.
+ list_field_names pode ser construido como
+ list_field_names=('nome', 'endereco', ('telefone', sexo'), 'dat_nasc')
+ """
+ r = []
+ for fieldname in self.list_field_names:
+ if isinstance(fieldname, tuple):
+ s = [force_text(self.model._meta.get_field(
+ fn).verbose_name) for fn in fieldname]
+ s = ' / '.join(s)
+ r.append(s)
+ else:
+ r.append(
+ self.model._meta.get_field(fieldname).verbose_name)
+ return r
def _as_row(self, obj):
- return [
- (get_field_display(obj, name)[1],
- self.resolve_url(DETAIL, args=(obj.id,)) if i == 0 else None)
- for i, name in enumerate(self.list_field_names)]
+ r = []
+ for i, name in enumerate(self.list_field_names):
+ url = self.resolve_url(
+ ACTION_DETAIL, args=(obj.id,)) if i == 0 else None
+
+ """Caso o crud list seja para uma relação ManyToManyField"""
+ if url and hasattr(self, 'crud') and\
+ hasattr(self.crud, 'is_m2m') and self.crud.is_m2m:
+ url = url + ('?pkk=' + self.kwargs['pk']
+ if 'pk' in self.kwargs else '')
+
+ """ se elemento de list_field_name for uma tupla, constrói a
+ informação com ' - ' se os campos forem simples,
+ ou com
se for m2m """
+ if isinstance(name, tuple):
+ s = ''
+ for j, n in enumerate(name):
+ ss = get_field_display(obj, n)[1]
+ ss = (
+ ('
' if '
' in ss else ' - ') + ss)\
+ if ss and j != 0 and s else ss
+ s += ss
+ r.append((s, url))
+ else:
+ r.append((get_field_display(obj, name)[1], url))
+ return r
def get_context_data(self, **kwargs):
- context = super(CrudListView, self).get_context_data(**kwargs)
+ """ Relevante se na implmentação do crud list, for informado
+ um formulário de pesquisa herdado ou o próprio ListWithSearchForm.
+ Só pode ser usado se o model relativo herdar de SearchMixin"""
+ if hasattr(self, 'form_search_class'):
+ q = str(self.request.GET.get('q'))\
+ if 'q' in self.request.GET else ''
+
+ o = self.request.GET['o'] if 'o' in self.request.GET else '1'
+
+ if 'form' not in kwargs:
+ initial = self.get_initial() if hasattr(
+ self, 'get_initial') else {}
+ initial.update({'q': q, 'o': o})
+ kwargs['form'] = self.form_search_class(
+ initial=initial)
+
+ count = self.object_list.count()
+ context = super().get_context_data(**kwargs)
context.setdefault('title', self.verbose_name_plural)
+ context['count'] = count
# pagination
if self.paginate_by:
@@ -142,16 +419,105 @@ class CrudListView(ListView):
context['NO_ENTRIES_MSG'] = self.no_entries_msg
+ qr = self.request.GET.copy()
+ if 'page' in qr:
+ del qr['page']
+ context['filter_url'] = (
+ '&' + qr.urlencode()) if len(qr) > 0 else ''
+ if 'o' in qr:
+ del qr['o']
+ context['ordering_url'] = (
+ '&' + qr.urlencode()) if len(qr) > 0 else ''
return context
-
-class CrudCreateView(FormMessagesMixin, CreateView):
+ def get_queryset(self):
+ queryset = super().get_queryset()
+
+ # form_search_class
+ # só pode ser usado em models que herdam de SearchMixin
+ if hasattr(self, 'form_search_class'):
+ request = self.request
+ if request.GET.get('q') is not None:
+ query = normalize(str(request.GET.get('q')))
+
+ query = query.split(' ')
+ if query:
+ q = models.Q()
+ for item in query:
+ if not item:
+ continue
+ q = q & models.Q(search__icontains=item)
+
+ if q:
+ queryset = queryset.filter(q)
+
+ list_field_names = self.list_field_names
+ o = '1'
+ desc = ''
+ if 'o' in self.request.GET:
+ o = self.request.GET['o']
+ desc = '-' if o.startswith('-') else ''
+
+ # Constroi a ordenação da listagem com base no que o usuário clicar
+ try:
+ fields_for_ordering = list_field_names[
+ (abs(int(o)) - 1) % len(list_field_names)]
+
+ if isinstance(fields_for_ordering, str):
+ fields_for_ordering = [fields_for_ordering, ]
+
+ ordering = ()
+ model = self.model
+ for fo in fields_for_ordering:
+ fm = model._meta.get_field(fo)
+ if hasattr(fm, 'related_model') and fm.related_model:
+ rmo = fm.related_model._meta.ordering
+ if rmo:
+ rmo = rmo[0]
+ if not isinstance(rmo, str):
+ rmo = rmo[0]
+ fo = '%s__%s' % (fo, rmo)
+
+ fo = desc + fo
+ ordering += (fo,)
+
+ model = self.model
+ model_ordering = model._meta.ordering
+ if model_ordering:
+ if isinstance(model_ordering, str):
+ model_ordering = (model_ordering,)
+ for mo in model_ordering:
+ if mo not in ordering:
+ ordering = ordering + (mo, )
+ queryset = queryset.order_by(*ordering)
+
+ print(ordering)
+ except Exception as e:
+ logger.error(string_concat(_(
+ 'ERRO: contrução da tupla de ordenação.'), str(e)))
+ elif hasattr(self, 'initial_order'):
+ queryset = queryset.order_by(*(self.initial_order))
+
+ if not self.request.user.is_authenticated():
+ return queryset
+
+ if self.container_field:
+ params = {}
+ params[self.container_field] = self.request.user.pk
+ queryset = queryset.filter(**params)
+
+ return queryset
+
+
+class CrudCreateView(PermissionRequiredContainerCrudMixin,
+ FormMessagesMixin, CreateView):
+ permission_required = (RP_ADD, )
@classmethod
def get_url_regex(cls):
return r'^create$'
- form_valid_message, form_invalid_message = FORM_MESSAGES[CREATE]
+ form_valid_message, form_invalid_message = FORM_MESSAGES[ACTION_CREATE]
@property
def cancel_url(self):
@@ -165,21 +531,200 @@ class CrudCreateView(FormMessagesMixin, CreateView):
'verbose_name': self.verbose_name})
return super(CrudCreateView, self).get_context_data(**kwargs)
+ def form_valid(self, form):
+ self.object = form.save(commit=False)
+ try:
+ self.object.owner = self.request.user
+ self.object.modifier = self.request.user
+ except:
+ pass
+
+ if self.container_field:
+ container = self.container_field.split('__')
+
+ if len(container) > 1:
+ container_model = getattr(
+ self.model, container[0]).field.related_model
-class CrudDetailView(DetailView):
+ params = {}
+ params['__'.join(
+ container[1:])] = self.request.user.pk
+
+ if 'pk' in self.kwargs:
+ params['pk'] = self.kwargs['pk']
+
+ container_data = container_model.objects.filter(
+ **params).first()
+
+ if not container_data:
+ raise Exception(
+ _('Não é permitido adicionar um registro '
+ 'sem estar em um Container'))
+
+ if hasattr(self, 'crud') and\
+ hasattr(self.crud, 'is_m2m') and self.crud.is_m2m:
+ setattr(
+ self.object, container[1], getattr(
+ container_data, container[1]))
+ response = super().form_valid(form)
+ getattr(self.object, container[0]).add(container_data)
+ return response
+ else:
+ setattr(self.object, container[0], container_data)
+
+ return super().form_valid(form)
+
+
+class CrudDetailView(PermissionRequiredContainerCrudMixin,
+ DetailView, MultipleObjectMixin):
+
+ permission_required = (RP_DETAIL, )
+ no_entries_msg = _('Nenhum registro Associado.')
+ paginate_by = 10
@classmethod
def get_url_regex(cls):
return r'^(?P\d+)$'
+ def get_rows(self, object_list):
+ return [self._as_row(obj) for obj in object_list]
+
+ def get_headers(self):
+ if not self.object_list:
+ return []
+ try:
+ obj = self.crud if hasattr(self, 'crud') else self
+ return [
+ (getattr(
+ self.object, obj.model_set).model._meta.get_field(
+ fieldname).verbose_name
+ if hasattr(self.object, fieldname) else
+ getattr(
+ self.object, obj.model_set).model._meta.get_field(
+ fieldname).related_model._meta.verbose_name_plural)
+ for fieldname in self.list_field_names_set]
+ except:
+ obj = self.crud if hasattr(self, 'crud') else self
+ return [getattr(
+ self.object,
+ obj.model_set).model._meta.verbose_name_plural]
+
+ def url_model_set_name(self, suffix):
+ return '%s_%s' % (
+ getattr(self.object,
+ self.crud.model_set).model._meta.model_name,
+ suffix)
+
+ def resolve_model_set_url(self, suffix, args=None):
+ obj = self.crud if hasattr(self, 'crud') else self
+ namespace = getattr(
+ self.object, obj.model_set).model._meta.app_config.name
+ return reverse('%s:%s' % (
+ namespace, self.url_model_set_name(suffix)),
+ args=args)
+
+ def _as_row(self, obj):
+ try:
+ return [(
+ get_field_display(obj, name)[1],
+ self.resolve_model_set_url(ACTION_DETAIL, args=(obj.id,))
+ if i == 0 else None)
+ for i, name in enumerate(self.list_field_names_set)]
+ except:
+ return [(
+ getattr(obj, name),
+ self.resolve_model_set_url(ACTION_DETAIL, args=(obj.id,))
+ if i == 0 else None)
+ for i, name in enumerate(self.list_field_names_set)]
+
+ def get_object(self, queryset=None):
+ return self.object
+
+ def get(self, request, *args, **kwargs):
+ self.object = self.model.objects.get(pk=kwargs.get('pk'))
+ obj = self.crud if hasattr(self, 'crud') else self
+ if hasattr(obj, 'model_set') and obj.model_set:
+ self.object_list = self.get_queryset()
+ context = self.get_context_data(object=self.object)
+ return self.render_to_response(context)
+
+ def get_queryset(self):
+ obj = self.crud if hasattr(self, 'crud') else self
+ queryset = getattr(self.object, obj.model_set).all()
+
+ if not self.request.user.is_authenticated():
+ return queryset
+
+ if self.container_field_set:
+ params = {}
+ params[self.container_field_set] = self.request.user.pk
+ return queryset.filter(**params)
+
+ return queryset
+
+ def get_context_data(self, **kwargs):
+ obj = self.crud if hasattr(self, 'crud') else self
+ if hasattr(obj, 'model_set') and obj.model_set:
+ count = self.object_list.count()
+ context = MultipleObjectMixin.get_context_data(self, **kwargs)
+ context['count'] = count
+ if self.paginate_by:
+ page_obj = context['page_obj']
+ paginator = context['paginator']
+ context['page_range'] = make_pagination(
+ page_obj.number, paginator.num_pages)
+
+ # rows
+ object_list = context['object_list']
+ context['headers'] = self.get_headers()
+ context['rows'] = self.get_rows(object_list)
+
+ context['NO_ENTRIES_MSG'] = self.no_entries_msg
+ else:
+ context = ContextMixin.get_context_data(self, **kwargs)
+ if self.object:
+ context['object'] = self.object
+ context_object_name = self.get_context_object_name(
+ self.object)
+ if context_object_name:
+ context[context_object_name] = self.object
+ context.update(kwargs)
+
+ return context
+
+ @property
+ def model_set_verbose_name(self):
+ obj = self.crud if hasattr(self, 'crud') else self
+ return getattr(
+ self.object,
+ obj.model_set).model._meta.verbose_name
+
+ @property
+ def model_set_verbose_name_plural(self):
+ obj = self.crud if hasattr(self, 'crud') else self
+ return getattr(
+ self.object,
+ obj.model_set).model._meta.verbose_name_plural
+
+
+class CrudUpdateView(PermissionRequiredContainerCrudMixin,
+ FormMessagesMixin, UpdateView):
+ permission_required = (RP_CHANGE, )
+
+ def form_valid(self, form):
+ self.object = form.save(commit=False)
+ try:
+ self.object.modifier = self.request.user
+ except:
+ pass
-class CrudUpdateView(FormMessagesMixin, UpdateView):
+ return super().form_valid(form)
@classmethod
def get_url_regex(cls):
return r'^(?P\d+)/edit$'
- form_valid_message, form_invalid_message = FORM_MESSAGES[UPDATE]
+ form_valid_message, form_invalid_message = FORM_MESSAGES[ACTION_UPDATE]
@property
def cancel_url(self):
@@ -189,13 +734,15 @@ class CrudUpdateView(FormMessagesMixin, UpdateView):
return self.detail_url
-class CrudDeleteView(FormMessagesMixin, DeleteView):
+class CrudDeleteView(PermissionRequiredContainerCrudMixin,
+ FormMessagesMixin, DeleteView):
+ permission_required = (RP_DELETE, )
@classmethod
def get_url_regex(cls):
return r'^(?P\d+)/delete$'
- form_valid_message, form_invalid_message = FORM_MESSAGES[DELETE]
+ form_valid_message, form_invalid_message = FORM_MESSAGES[ACTION_DELETE]
@property
def cancel_url(self):
@@ -233,19 +780,366 @@ class Crud:
return [url(regex, view.as_view(), name=view.url_name(suffix))
for regex, view, suffix in [
- (CrudListView.get_url_regex(), CrudListView, LIST),
- (CrudCreateView.get_url_regex(), CrudCreateView, CREATE),
- (CrudDetailView.get_url_regex(), CrudDetailView, DETAIL),
- (CrudUpdateView.get_url_regex(), CrudUpdateView, UPDATE),
- (CrudDeleteView.get_url_regex(), CrudDeleteView, DELETE),
+ (CrudListView.get_url_regex(), CrudListView, ACTION_LIST),
+ (CrudCreateView.get_url_regex(),
+ CrudCreateView, ACTION_CREATE),
+ (CrudDetailView.get_url_regex(),
+ CrudDetailView, ACTION_DETAIL),
+ (CrudUpdateView.get_url_regex(),
+ CrudUpdateView, ACTION_UPDATE),
+ (CrudDeleteView.get_url_regex(),
+ CrudDeleteView, ACTION_DELETE),
]]
@classonlymethod
- def build(cls, _model, _help_path):
+ def build(cls, _model, _help_path, _model_set=None, list_field_names=[]):
- class ModelCrud(cls):
- model = _model
- help_path = _help_path
+ def create_class_with_list_field(_list_field_names):
+ class ModelCrud(cls):
+ model = _model
+ model_set = _model_set
+ help_path = _help_path
+
+ class BaseMixin(cls.BaseMixin):
+ list_field_names = _list_field_names
+ return ModelCrud
+
+ def create_class():
+ class ModelCrud(cls):
+ model = _model
+ model_set = _model_set
+ help_path = _help_path
+ return ModelCrud
+
+ ModelCrud = create_class() if not list_field_names\
+ else create_class_with_list_field(list_field_names)
ModelCrud.__name__ = '%sCrud' % _model.__name__
+
return ModelCrud
+
+
+class CrudAux(Crud):
+
+ @classonlymethod
+ def build(cls, _model, _help_path, _model_set=None, list_field_names=[]):
+
+ ModelCrud = Crud.build(
+ _model, _help_path, _model_set, list_field_names)
+
+ class ModelCrudAux(ModelCrud):
+
+ class BaseMixin(ModelCrud.BaseMixin):
+ permission_required = ('base.view_tabelas_auxiliares',)
+
+ return ModelCrudAux
+
+
+class MasterDetailCrud(Crud):
+ is_m2m = False
+
+ class BaseMixin(Crud.BaseMixin):
+
+ @property
+ def list_url(self):
+ return self.resolve_url(ACTION_LIST, args=(self.kwargs['pk'],))\
+ if self.request.user.has_perm(self.permission(RP_LIST)) else ''
+
+ @property
+ def create_url(self):
+ return self.resolve_url(ACTION_CREATE, args=(self.kwargs['pk'],))\
+ if self.request.user.has_perm(self.permission(RP_ADD)) else ''
+
+ @property
+ def detail_url(self):
+ pkk = self.request.GET['pkk'] if 'pkk' in self.request.GET else ''
+ return (super().detail_url + (('?pkk=' + pkk) if pkk else ''))\
+ if self.request.user.has_perm(
+ self.permission(RP_DETAIL)) else ''
+
+ @property
+ def update_url(self):
+ pkk = self.request.GET['pkk'] if 'pkk' in self.request.GET else ''
+ return (super().update_url + (('?pkk=' + pkk) if pkk else ''))\
+ if self.request.user.has_perm(
+ self.permission(RP_CHANGE)) else ''
+
+ @property
+ def delete_url(self):
+ return super().delete_url\
+ if self.request.user.has_perm(
+ self.permission(RP_DELETE)) else ''
+
+ def get_context_data(self, **kwargs):
+ obj = self.crud if hasattr(self, 'crud') else self
+ self.object = getattr(self, 'object', None)
+ parent_object = None
+ if self.object:
+ if '__' in obj.parent_field:
+ fields = obj.parent_field.split('__')
+ parent_object = self.object
+ for field in fields:
+ parent_object = getattr(parent_object, field)
+ else:
+ parent_object = getattr(self.object, obj.parent_field)
+ if not isinstance(parent_object, models.Model):
+ if parent_object.count() > 1:
+ if 'pkk' not in self.request.GET:
+ raise Http404
+ root_pk = self.request.GET['pkk']
+ parent_object = parent_object.filter(id=root_pk)
+
+ parent_object = parent_object.first()
+
+ if not parent_object:
+ raise Http404
+ root_pk = parent_object.pk
+ else:
+ root_pk = self.kwargs['pk'] # in list and create
+ kwargs.setdefault('root_pk', root_pk)
+ context = super(CrudBaseMixin, self).get_context_data(**kwargs)
+
+ if parent_object:
+ context['title'] = '%s (%s)' % (
+ self.object, parent_object)
+
+ return context
+
+ class ListView(Crud.ListView):
+ permission_required = RP_LIST,
+
+ @classmethod
+ def get_url_regex(cls):
+ return r'^(?P\d+)/%s$' % cls.model._meta.model_name
+
+ def get_context_data(self, **kwargs):
+ obj = self.crud if hasattr(self, 'crud') else self
+ count = self.object_list.count()
+ context = CrudListView.get_context_data(self, **kwargs)
+ context['count'] = count
+
+ parent_model = None
+ if '__' in obj.parent_field:
+ fields = obj.parent_field.split('__')
+ parent_model = self.model
+ for field in fields:
+ parent_model = getattr(
+ parent_model, field).field.related_model
+ else:
+ parent_model = getattr(
+ self.model, obj.parent_field).field.related_model
+
+ params = {'pk': kwargs['root_pk']}
+
+ if self.container_field:
+ container = self.container_field.split('__')
+ if len(container) > 1:
+ params['__'.join(container[1:])] = self.request.user.pk
+
+ try:
+ parent_object = parent_model.objects.get(**params)
+ except:
+ raise Http404()
+
+ context[
+ 'title'] = '%s (%s)' % (
+ context['title'], parent_object)
+ return context
+
+ def get_queryset(self):
+ obj = self.crud if hasattr(self, 'crud') else self
+ qs = super().get_queryset()
+
+ kwargs = {obj.parent_field: self.kwargs['pk']}
+
+ """if self.container_field:
+ kwargs[self.container_field] = self.request.user.pk"""
+
+ return qs.filter(**kwargs)
+
+ class CreateView(Crud.CreateView):
+ permission_required = RP_ADD,
+
+ def dispatch(self, request, *args, **kwargs):
+ return PermissionRequiredMixin.dispatch(
+ self, request, *args, **kwargs)
+
+ @classmethod
+ def get_url_regex(cls):
+ return r'^(?P\d+)/%s/create$' % cls.model._meta.model_name
+
+ def get_form(self, form_class=None):
+ obj = self.crud if hasattr(self, 'crud') else self
+ form = super(CrudCreateView,
+ self).get_form(self.form_class)
+ if not obj.is_m2m:
+ parent_field = obj.parent_field.split('__')[0]
+ field = self.model._meta.get_field(parent_field)
+ parent = field.related_model.objects.get(pk=self.kwargs['pk'])
+ setattr(form.instance, parent_field, parent)
+ return form
+
+ def get_context_data(self, **kwargs):
+ obj = self.crud if hasattr(self, 'crud') else self
+ context = Crud.CreateView.get_context_data(
+ self, **kwargs)
+
+ params = {'pk': self.kwargs['pk']}
+ if self.container_field:
+ parent_model = getattr(
+ self.model, obj.parent_field).field.related_model
+
+ container = self.container_field.split('__')
+ if len(container) > 1:
+ params['__'.join(container[1:])] = self.request.user.pk
+
+ try:
+ parent = parent_model.objects.get(**params)
+ except:
+ raise Http404()
+ else:
+ parent_field = obj.parent_field.split('__')[0]
+
+ field = self.model._meta.get_field(parent_field)
+ parent = field.related_model.objects.get(**params)
+ if parent:
+ context['title'] = '%s (%s)' % (
+ context['title'], parent)
+
+ return context
+
+ class UpdateView(Crud.UpdateView):
+ permission_required = RP_CHANGE,
+
+ @classmethod
+ def get_url_regex(cls):
+ return r'^%s/(?P\d+)/edit$' % cls.model._meta.model_name
+
+ def get(self, request, *args, **kwargs):
+ return Crud.UpdateView.get(self, request, *args, **kwargs)
+
+ class DeleteView(Crud.DeleteView):
+ permission_required = RP_DELETE,
+
+ @classmethod
+ def get_url_regex(cls):
+ return r'^%s/(?P\d+)/delete$' % cls.model._meta.model_name
+
+ def get_success_url(self):
+ obj = self.crud if hasattr(self, 'crud') else self
+ parent_object = getattr(
+ self.get_object(), obj.parent_field)
+ if not isinstance(parent_object, models.Model):
+ if parent_object.count() > 1:
+ if 'pkk' not in self.request.GET:
+ raise Http404
+ root_pk = self.request.GET['pkk']
+ parent_object = parent_object.filter(id=root_pk)
+
+ parent_object = parent_object.first()
+
+ if not parent_object:
+ raise Http404
+ root_pk = parent_object.pk
+
+ pk = root_pk
+ return self.resolve_url(ACTION_LIST, args=(pk,))
+
+ class DetailView(Crud.DetailView):
+ permission_required = RP_DETAIL,
+ template_name = 'crud/detail_detail.html'
+
+ @classmethod
+ def get_url_regex(cls):
+ return r'^%s/(?P\d+)$' % cls.model._meta.model_name
+
+ @property
+ def detail_list_url(self):
+ obj = self.crud if hasattr(self, 'crud') else self
+ if not obj.ListView.permission_required or self.request.user.has_perm(self.permission(RP_LIST)):
+ if '__' in obj.parent_field:
+ fields = obj.parent_field.split('__')
+ parent_object = self.object
+ for field in fields:
+ parent_object = getattr(parent_object, field)
+ else:
+ parent_object = getattr(self.object, obj.parent_field)
+
+ if not isinstance(parent_object, models.Model):
+ if parent_object.count() > 1:
+ if 'pkk' not in self.request.GET:
+ raise Http404
+ root_pk = self.request.GET['pkk']
+ parent_object = parent_object.filter(id=root_pk)
+
+ parent_object = parent_object.first()
+
+ if not parent_object:
+ raise Http404
+ root_pk = parent_object.pk
+
+ pk = root_pk
+ return self.resolve_url(ACTION_LIST, args=(pk,))
+ else:
+ return ''
+
+ @property
+ def detail_create_url(self):
+ obj = self.crud if hasattr(self, 'crud') else self
+ if self.request.user.has_perm(self.permission(RP_ADD)):
+ parent_field = obj.parent_field.split('__')[0]
+ parent_object = getattr(self.object, parent_field)
+
+ if not isinstance(parent_object, models.Model):
+ if parent_object.count() > 1:
+ if 'pkk' not in self.request.GET:
+ raise Http404
+ root_pk = self.request.GET['pkk']
+ parent_object = parent_object.filter(id=root_pk)
+
+ parent_object = parent_object.first()
+
+ if not parent_object:
+ raise Http404
+ root_pk = parent_object.pk
+ pk = root_pk
+ return self.resolve_url(ACTION_CREATE, args=(pk,))
+ else:
+ return ''
+
+ @property
+ def detail_set_create_url(self):
+ obj = self.crud if hasattr(self, 'crud') else self
+ if hasattr(obj, 'model_set') and self.request.user.has_perm(
+ self.permission_set(RP_ADD)):
+ root_pk = self.object .pk
+ pk = root_pk
+ return self.resolve_url_set(ACTION_CREATE, args=(pk,))
+ else:
+ return ''
+
+ @property
+ def detail_root_detail_url(self):
+ """
+ Implementar retorno para o parent_field imediato no caso de
+ edição em cascata de MasterDetailDetail...
+ """
+ return ''
+ obj = self.crud if hasattr(self, 'crud') else self
+ if hasattr(obj, 'parent_field'):
+ parent_field = obj.parent_field.split('__')[0]
+
+ root_pk = self.object .pk
+ pk = root_pk
+ return self.resolve_url(ACTION_DELETE, args=(pk,))
+ else:
+ return ''
+
+ @classonlymethod
+ def build(cls, model, parent_field, help_path,
+ _model_set=None, list_field_names=[]):
+ crud = super(MasterDetailCrud, cls).build(
+ model, help_path, _model_set=_model_set,
+ list_field_names=list_field_names)
+ crud.parent_field = parent_field
+ return crud
diff --git a/sapl/crud/masterdetail.py b/sapl/crud/masterdetail.py
index 2d0bf32d1..91c8de5ba 100644
--- a/sapl/crud/masterdetail.py
+++ b/sapl/crud/masterdetail.py
@@ -1,21 +1,21 @@
from django.utils.decorators import classonlymethod
-from .base import (CREATE, LIST, Crud, CrudBaseMixin, CrudCreateView,
+from .base import (ACTION_CREATE, ACTION_LIST, Crud, CrudBaseMixin, CrudCreateView,
CrudDeleteView, CrudDetailView, CrudListView,
CrudUpdateView)
-class MasterDetailCrud(Crud):
+class MasterDetailCrud__OBSOLETO(Crud):
class BaseMixin(CrudBaseMixin):
@property
def list_url(self):
- return self.resolve_url(LIST, args=(self.kwargs['pk'],))
+ return self.resolve_url(ACTION_LIST, args=(self.kwargs['pk'],))
@property
def create_url(self):
- return self.resolve_url(CREATE, args=(self.kwargs['pk'],))
+ return self.resolve_url(ACTION_CREATE, args=(self.kwargs['pk'],))
def get_context_data(self, **kwargs):
obj = getattr(self, 'object', None)
@@ -24,7 +24,7 @@ class MasterDetailCrud(Crud):
else:
root_pk = self.kwargs['pk'] # in list and create
kwargs.setdefault('root_pk', root_pk)
- return super(MasterDetailCrud.BaseMixin,
+ return super(MasterDetailCrud__OBSOLETO.BaseMixin,
self).get_context_data(**kwargs)
class ListView(CrudListView):
@@ -34,7 +34,8 @@ class MasterDetailCrud(Crud):
return r'^(?P\d+)/%s$' % cls.model._meta.model_name
def get_queryset(self):
- qs = super(MasterDetailCrud.ListView, self).get_queryset()
+ qs = super(
+ MasterDetailCrud__OBSOLETO.ListView, self).get_queryset()
kwargs = {self.crud.parent_field: self.kwargs['pk']}
return qs.filter(**kwargs)
@@ -45,7 +46,7 @@ class MasterDetailCrud(Crud):
return r'^(?P\d+)/%s/create$' % cls.model._meta.model_name
def get_form(self, form_class=None):
- form = super(MasterDetailCrud.CreateView,
+ form = super(MasterDetailCrud__OBSOLETO.CreateView,
self).get_form(self.form_class)
field = self.model._meta.get_field(self.crud.parent_field)
parent = field.related_model.objects.get(pk=self.kwargs['pk'])
@@ -72,10 +73,10 @@ class MasterDetailCrud(Crud):
def get_success_url(self):
pk = getattr(self.get_object(), self.crud.parent_field).pk
- return self.resolve_url(LIST, args=(pk,))
+ return self.resolve_url(ACTION_LIST, args=(pk,))
@classonlymethod
def build(cls, model, parent_field, help_path):
- crud = super(MasterDetailCrud, cls).build(model, help_path)
+ crud = super(MasterDetailCrud__OBSOLETO, cls).build(model, help_path)
crud.parent_field = parent_field
return crud
diff --git a/sapl/crud/urls.py b/sapl/crud/urls.py
index 8b7da50fe..53b6e36fa 100644
--- a/sapl/crud/urls.py
+++ b/sapl/crud/urls.py
@@ -1,4 +1,13 @@
+from builtins import LookupError
+
+from django import apps
from django.conf.urls import include, url
+from django.contrib.auth.management import _get_all_permissions
+from django.core import exceptions
+from django.db import models, router
+from django.db.utils import DEFAULT_DB_ALIAS
+from django.utils.translation import string_concat
+
urlpatterns = [
url(r'', include('stub_app.urls')),
diff --git a/sapl/materia/views.py b/sapl/materia/views.py
index 75cd34b94..2e412c532 100644
--- a/sapl/materia/views.py
+++ b/sapl/materia/views.py
@@ -2,12 +2,12 @@ from datetime import datetime
from random import choice
from string import ascii_letters, digits
+from braces.views import PermissionRequiredMixin
from crispy_forms.helper import FormHelper
from crispy_forms.layout import HTML, Button
from django.conf import settings
from django.contrib import messages
from django.contrib.auth import get_user_model
-from django.contrib.auth.mixins import PermissionRequiredMixin
from django.contrib.auth.tokens import default_token_generator
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from django.core.mail import send_mail
@@ -28,8 +28,7 @@ from sapl.compilacao.views import IntegracaoTaView
from sapl.crispy_layout_mixin import SaplFormLayout, form_actions, to_row
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
CrudDeleteView, CrudDetailView, CrudListView,
- CrudUpdateView, make_pagination)
-from sapl.crud.masterdetail import MasterDetailCrud
+ CrudUpdateView, make_pagination, MasterDetailCrud)
from sapl.norma.models import LegislacaoCitada
from sapl.utils import (TURNO_TRAMITACAO_CHOICES, YES_NO_CHOICES, autor_label,
autor_modal, gerar_hash_arquivo, get_base_url,
@@ -74,17 +73,12 @@ class OrigemCrud(Crud):
model = Origem
help_path = 'origem'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
-
- def has_permission(self):
- return permissao_tb_aux(self)
-
class TipoMateriaCrud(Crud):
model = TipoMateriaLegislativa
help_path = 'tipo_materia_legislativa'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -94,7 +88,7 @@ class RegimeTramitacaoCrud(Crud):
model = RegimeTramitacao
help_path = 'regime_tramitacao'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -104,7 +98,7 @@ class TipoDocumentoCrud(Crud):
model = TipoDocumento
help_path = 'tipo_documento'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -114,7 +108,7 @@ class TipoFimRelatoriaCrud(Crud):
model = TipoFimRelatoria
help_path = 'fim_relatoria'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -124,7 +118,7 @@ class TipoAutorCrud(Crud):
model = TipoAutor
help_path = 'tipo_autor'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -156,7 +150,7 @@ class AutorCrud(Crud):
model = Autor
help_path = 'autor'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
list_field_names = ['tipo', 'nome']
def has_permission(self):
@@ -233,7 +227,7 @@ class OrgaoCrud(Crud):
model = Orgao
help_path = 'orgao'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -243,7 +237,7 @@ class TipoProposicaoCrud(Crud):
model = TipoProposicao
help_path = 'tipo_proposicao'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -253,7 +247,7 @@ class StatusTramitacaoCrud(Crud):
model = StatusTramitacao
help_path = 'status_tramitacao'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -300,15 +294,15 @@ class UnidadeTramitacaoCrud(Crud):
model = UnidadeTramitacao
help_path = 'unidade_tramitacao'
- class CreateView(PermissionRequiredMixin, CrudCreateView):
+ class CreateView(CrudCreateView):
permission_required = permissoes_materia()
form_class = UnidadeTramitacaoForm
- class UpdateView(PermissionRequiredMixin, CrudUpdateView):
+ class UpdateView(CrudUpdateView):
permission_required = permissoes_materia()
form_class = UnidadeTramitacaoForm
- class DeleteView(PermissionRequiredMixin, CrudDeleteView):
+ class DeleteView(CrudDeleteView):
permission_required = permissoes_materia()
@@ -461,7 +455,7 @@ class ProposicaoCrud(Crud):
list_field_names = ['data_envio', 'descricao',
'tipo', 'data_recebimento']
- class CreateView(PermissionRequiredMixin, CrudCreateView):
+ class CreateView(CrudCreateView):
form_class = ProposicaoForm
permission_required = {'materia.add_proposicao'}
@@ -489,7 +483,7 @@ class ProposicaoCrud(Crud):
else:
return {'autor': autor_id}
- class UpdateView(PermissionRequiredMixin, CrudUpdateView):
+ class UpdateView(CrudUpdateView):
form_class = ProposicaoForm
permission_required = permissoes_autor()
@@ -525,7 +519,7 @@ class ProposicaoCrud(Crud):
messages.add_message(self.request, messages.ERROR, msg)
return False
- class DetailView(PermissionRequiredMixin, CrudDetailView):
+ class DetailView(CrudDetailView):
permission_required = permissoes_autor()
def has_permission(self):
@@ -542,7 +536,7 @@ class ProposicaoCrud(Crud):
context['subnav_template_name'] = ''
return context
- class ListView(PermissionRequiredMixin, CrudListView):
+ class ListView(CrudListView):
ordering = ['-data_envio', 'descricao']
permission_required = permissoes_autor()
@@ -572,7 +566,7 @@ class ProposicaoCrud(Crud):
return lista
- class DeleteView(PermissionRequiredMixin, CrudDeleteView):
+ class DeleteView(CrudDeleteView):
permission_required = {'materia.delete_proposicao'}
def has_permission(self):
@@ -637,7 +631,7 @@ class RelatoriaCrud(MasterDetailCrud):
parent_field = 'materia'
help_path = ''
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
permission_required = permissoes_materia()
form_class = RelatoriaForm
@@ -658,11 +652,11 @@ class RelatoriaCrud(MasterDetailCrud):
return {'comissao': localizacao}
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
permission_required = permissoes_materia()
form_class = RelatoriaForm
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
@@ -674,8 +668,9 @@ class TramitacaoCrud(MasterDetailCrud):
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['data_tramitacao', 'unidade_tramitacao_local',
'unidade_tramitacao_destino', 'status']
+ initial_order = '-data_tramitacao'
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
form_class = TramitacaoForm
permission_required = permissoes_materia()
@@ -692,7 +687,7 @@ class TramitacaoCrud(MasterDetailCrud):
do_envia_email_tramitacao(request, materia)
return super(CreateView, self).post(request, *args, **kwargs)
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
form_class = TramitacaoUpdateForm
permission_required = permissoes_materia()
@@ -713,7 +708,7 @@ class TramitacaoCrud(MasterDetailCrud):
kwargs = {self.crud.parent_field: self.kwargs['pk']}
return qs.filter(**kwargs).order_by('-data_tramitacao', '-id')
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
def delete(self, request, *args, **kwargs):
@@ -771,7 +766,7 @@ class DocumentoAcessorioCrud(MasterDetailCrud):
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['nome', 'tipo', 'data', 'autor', 'arquivo']
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
form_class = DocumentoAcessorioForm
permission_required = permissoes_materia()
@@ -784,7 +779,7 @@ class DocumentoAcessorioCrud(MasterDetailCrud):
context['helper'] = self.helper
return context
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
form_class = DocumentoAcessorioForm
permission_required = permissoes_materia()
@@ -797,7 +792,7 @@ class DocumentoAcessorioCrud(MasterDetailCrud):
context['helper'] = self.helper
return context
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
@@ -806,15 +801,15 @@ class AutoriaCrud(MasterDetailCrud):
parent_field = 'materia'
help_path = ''
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
form_class = AutoriaForm
permission_required = permissoes_materia()
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
form_class = AutoriaForm
permission_required = permissoes_materia()
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
@@ -823,15 +818,15 @@ class DespachoInicialCrud(MasterDetailCrud):
parent_field = 'materia'
help_path = ''
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
form_class = DespachoInicialForm
permission_required = permissoes_materia()
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
form_class = DespachoInicialForm
permission_required = permissoes_materia()
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
@@ -848,11 +843,11 @@ class LegislacaoCitadaCrud(MasterDetailCrud):
return reverse('%s:%s' % (namespace, self.url_name(suffix)),
args=args)
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
form_class = LegislacaoCitadaForm
permission_required = permissoes_materia()
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
form_class = LegislacaoCitadaForm
permission_required = permissoes_materia()
@@ -862,7 +857,7 @@ class LegislacaoCitadaCrud(MasterDetailCrud):
self.initial['ano'] = self.object.norma.ano
return self.initial
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
class DetailView(MasterDetailCrud.DetailView):
@@ -877,15 +872,15 @@ class NumeracaoCrud(MasterDetailCrud):
parent_field = 'materia'
help_path = ''
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
form_class = NumeracaoForm
permission_required = permissoes_materia()
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
form_class = NumeracaoForm
permission_required = permissoes_materia()
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
@@ -897,11 +892,11 @@ class AnexadaCrud(MasterDetailCrud):
class BaseMixin(MasterDetailCrud.BaseMixin):
list_field_names = ['materia_anexada', 'data_anexacao']
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
form_class = AnexadaForm
permission_required = permissoes_materia()
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
form_class = AnexadaForm
permission_required = permissoes_materia()
@@ -918,7 +913,7 @@ class AnexadaCrud(MasterDetailCrud):
def layout_key(self):
return 'AnexadaDetail'
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_materia()
@@ -929,13 +924,13 @@ class MateriaLegislativaCrud(Crud):
class BaseMixin(CrudBaseMixin):
list_field_names = ['tipo', 'numero', 'ano', 'data_apresentacao']
- class CreateView(PermissionRequiredMixin, CrudCreateView):
+ class CreateView(CrudCreateView):
permission_required = permissoes_materia()
- class UpdateView(PermissionRequiredMixin, CrudUpdateView):
+ class UpdateView(CrudUpdateView):
permission_required = permissoes_materia()
- class DeleteView(PermissionRequiredMixin, CrudDeleteView):
+ class DeleteView(CrudDeleteView):
permission_required = permissoes_materia()
diff --git a/sapl/norma/views.py b/sapl/norma/views.py
index 396695f13..24a243e81 100644
--- a/sapl/norma/views.py
+++ b/sapl/norma/views.py
@@ -20,7 +20,7 @@ class AssuntoNormaCrud(Crud):
model = AssuntoNorma
help_path = 'assunto_norma_juridica'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
permission_required = permissoes_norma()
list_field_names = ['assunto', 'descricao']
@@ -29,7 +29,7 @@ class TipoNormaCrud(Crud):
model = TipoNormaJuridica
help_path = 'tipo_norma_juridica'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
permission_required = permissoes_norma()
list_field_names = ['equivalente_lexml', 'sigla', 'descricao']
@@ -38,7 +38,7 @@ class NormaCrud(Crud):
model = NormaJuridica
help_path = 'norma_juridica'
- class UpdateView(PermissionRequiredMixin, CrudUpdateView):
+ class UpdateView(CrudUpdateView):
form_class = NormaJuridicaForm
permission_required = permissoes_norma()
@@ -54,7 +54,7 @@ class NormaCrud(Crud):
self.initial['numero_materia'] = norma.materia.numero
return self.initial.copy()
- class CreateView(PermissionRequiredMixin, CrudCreateView):
+ class CreateView(CrudCreateView):
form_class = NormaJuridicaForm
permission_required = permissoes_norma()
@@ -62,7 +62,7 @@ class NormaCrud(Crud):
def layout_key(self):
return 'NormaJuridicaCreate'
- class DeleteView(PermissionRequiredMixin, CrudDeleteView):
+ class DeleteView(CrudDeleteView):
permission_required = permissoes_norma()
class BaseMixin(CrudBaseMixin):
diff --git a/sapl/parlamentares/views.py b/sapl/parlamentares/views.py
index 9d3dde7c5..1f0639da5 100644
--- a/sapl/parlamentares/views.py
+++ b/sapl/parlamentares/views.py
@@ -1,5 +1,4 @@
from django.contrib import messages
-from django.contrib.auth.mixins import PermissionRequiredMixin
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
@@ -12,8 +11,7 @@ from django.views.generic import FormView, ListView
from sapl.comissoes.models import Participacao
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
CrudDeleteView, CrudDetailView, CrudListView,
- CrudUpdateView)
-from sapl.crud.masterdetail import MasterDetailCrud
+ CrudUpdateView, MasterDetailCrud)
from sapl.materia.models import Proposicao, Relatoria
from sapl.utils import permissao_tb_aux, permissoes_parlamentares
@@ -50,10 +48,10 @@ class FrenteCrud(Crud):
def has_permission(self):
return permissao_tb_aux(self)
- class CreateView(PermissionRequiredMixin, CrudCreateView):
+ class CreateView(CrudCreateView):
form_class = FrenteForm
- class UpdateView(PermissionRequiredMixin, CrudUpdateView):
+ class UpdateView(CrudUpdateView):
form_class = FrenteForm
@@ -65,13 +63,13 @@ class RelatoriaParlamentarCrud(MasterDetailCrud):
class ListView(MasterDetailCrud.ListView):
permission_required = permissoes_parlamentares()
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
permission_required = permissoes_parlamentares()
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
permission_required = permissoes_parlamentares()
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_parlamentares()
@@ -102,13 +100,13 @@ class ProposicaoParlamentarCrud(MasterDetailCrud):
else:
return proposicoes
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
permission_required = permissoes_parlamentares()
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
permission_required = permissoes_parlamentares()
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_parlamentares()
@@ -140,13 +138,13 @@ class ParticipacaoParlamentarCrud(MasterDetailCrud):
def get_headers(self):
return ['Comissão', 'Cargo', 'Período']
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
permission_required = permissoes_parlamentares()
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
permission_required = permissoes_parlamentares()
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_parlamentares()
@@ -154,7 +152,7 @@ class CargoMesaCrud(Crud):
model = CargoMesa
help_path = 'cargo_mesa'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -164,7 +162,7 @@ class PartidoCrud(Crud):
model = Partido
help_path = 'partidos'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -174,7 +172,7 @@ class SessaoLegislativaCrud(Crud):
model = SessaoLegislativa
help_path = 'sessao_legislativa'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -184,7 +182,7 @@ class TipoDependenteCrud(Crud):
model = TipoDependente
help_path = 'nivel_instrucao'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -194,7 +192,7 @@ class NivelInstrucaoCrud(Crud):
model = NivelInstrucao
help_path = 'tipo_dependente'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -204,7 +202,7 @@ class TipoAfastamentoCrud(Crud):
model = TipoAfastamento
help_path = 'tipo_afastamento'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -214,7 +212,7 @@ class TipoMilitarCrud(Crud):
model = SituacaoMilitar
help_path = 'tipo_situa_militar'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -225,19 +223,19 @@ class DependenteCrud(MasterDetailCrud):
parent_field = 'parlamentar'
help_path = ''
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
permission_required = permissoes_parlamentares()
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
permission_required = permissoes_parlamentares()
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_parlamentares()
- class ListView(PermissionRequiredMixin, MasterDetailCrud.ListView):
+ class ListView(MasterDetailCrud.ListView):
permission_required = permissoes_parlamentares()
- class DetailView(PermissionRequiredMixin, MasterDetailCrud.DetailView):
+ class DetailView(MasterDetailCrud.DetailView):
permission_required = permissoes_parlamentares()
@@ -249,13 +247,13 @@ class MandatoCrud(MasterDetailCrud):
class ListView(MasterDetailCrud.ListView):
ordering = ('-legislatura__numero')
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
permission_required = permissoes_parlamentares()
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
permission_required = permissoes_parlamentares()
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_parlamentares()
@@ -266,7 +264,7 @@ class ColigacaoCrud(Crud):
class ListView(CrudListView):
ordering = ('-numero_votos', 'nome')
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -294,7 +292,7 @@ class ComposicaoColigacaoCrud(MasterDetailCrud):
class ListView(MasterDetailCrud.ListView):
ordering = '-partido__sigla'
- class BaseMixin(PermissionRequiredMixin, MasterDetailCrud.BaseMixin):
+ class BaseMixin(MasterDetailCrud.BaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -310,7 +308,7 @@ class LegislaturaCrud(Crud):
class UpdateView(CrudUpdateView):
form_class = LegislaturaForm
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
def has_permission(self):
return permissao_tb_aux(self)
@@ -321,15 +319,15 @@ class FiliacaoCrud(MasterDetailCrud):
parent_field = 'parlamentar'
help_path = ''
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
form_class = FiliacaoForm
permission_required = permissoes_parlamentares()
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
form_class = FiliacaoForm
permission_required = permissoes_parlamentares()
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_parlamentares()
class ListView(MasterDetailCrud.ListView):
@@ -362,11 +360,11 @@ class ParlamentarCrud(Crud):
else:
return ['parlamentares/parlamentar_perfil_publico.html']
- class UpdateView(PermissionRequiredMixin, CrudUpdateView):
+ class UpdateView(CrudUpdateView):
form_class = ParlamentarForm
permission_required = permissoes_parlamentares()
- class CreateView(PermissionRequiredMixin, CrudCreateView):
+ class CreateView(CrudCreateView):
form_class = ParlamentarCreateForm
permission_required = permissoes_parlamentares()
@@ -374,7 +372,7 @@ class ParlamentarCrud(Crud):
def layout_key(self):
return 'ParlamentarCreate'
- class DeleteView(PermissionRequiredMixin, CrudDeleteView):
+ class DeleteView(CrudDeleteView):
form_class = ParlamentarCreateForm
permission_required = permissoes_parlamentares()
diff --git a/sapl/protocoloadm/views.py b/sapl/protocoloadm/views.py
index 4ea8d86a7..45738735e 100644
--- a/sapl/protocoloadm/views.py
+++ b/sapl/protocoloadm/views.py
@@ -1,9 +1,8 @@
-import json
from datetime import date, datetime
+import json
-from braces.views import FormValidMessageMixin
+from braces.views import FormValidMessageMixin, PermissionRequiredMixin
from django.contrib import messages
-from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.exceptions import ObjectDoesNotExist
from django.core.urlresolvers import reverse
from django.db.models import Max, Q
@@ -14,15 +13,15 @@ from django.views.generic import CreateView, DetailView, FormView, ListView
from django.views.generic.base import TemplateView
from django_filters.views import FilterView
-import sapl.crud.base
from sapl.base.models import AppConfig
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
- CrudDeleteView, CrudDetailView, CrudListView,
- CrudUpdateView, make_pagination)
-from sapl.crud.masterdetail import MasterDetailCrud
+ CrudDetailView, CrudDeleteView,
+ CrudListView, CrudUpdateView,
+ make_pagination, MasterDetailCrud)
from sapl.materia.models import TipoMateriaLegislativa
from sapl.utils import (create_barcode, get_client_ip, permissoes_adm,
permissoes_protocoloadm)
+import sapl.crud.base
from .forms import (AnularProcoloAdmForm, DocumentoAcessorioAdministrativoForm,
DocumentoAdministrativoFilterSet,
@@ -35,6 +34,7 @@ from .models import (Autor, DocumentoAcessorioAdministrativo,
TipoDocumentoAdministrativo, TipoInstituicao,
TramitacaoAdministrativo)
+
TipoDocumentoAdministrativoCrud = Crud.build(TipoDocumentoAdministrativo, '')
DocumentoAcessorioAdministrativoCrud = Crud.build(
DocumentoAcessorioAdministrativo, '')
@@ -53,16 +53,16 @@ class DocumentoAdministrativoCrud(Crud):
'numero_protocolo', 'assunto',
'interessado', 'tramitacao', 'texto_integral']
- class CreateView(PermissionRequiredMixin, CrudCreateView):
+ class CreateView(CrudCreateView):
permission_required = permissoes_adm()
- class UpdateView(PermissionRequiredMixin, CrudUpdateView):
+ class UpdateView(CrudUpdateView):
permission_required = permissoes_adm()
- class DeleteView(PermissionRequiredMixin, CrudDeleteView):
+ class DeleteView(CrudDeleteView):
permission_required = permissoes_adm()
- class ListView(PermissionRequiredMixin, CrudListView):
+ class ListView(CrudListView):
permission_required = permissoes_adm()
def has_permission(self):
@@ -75,7 +75,7 @@ class DocumentoAdministrativoCrud(Crud):
perms = self.get_permission_required()
return self.request.user.has_perms(perms)
- class DetailView(PermissionRequiredMixin, CrudDetailView):
+ class DetailView(CrudDetailView):
permission_required = permissoes_adm()
def has_permission(self):
@@ -99,13 +99,13 @@ class StatusTramitacaoAdministrativoCrud(Crud):
class ListView(CrudListView):
ordering = 'sigla'
- class CreateView(PermissionRequiredMixin, CrudCreateView):
+ class CreateView(CrudCreateView):
permission_required = permissoes_adm()
- class UpdateView(PermissionRequiredMixin, CrudUpdateView):
+ class UpdateView(CrudUpdateView):
permission_required = permissoes_adm()
- class DeleteView(PermissionRequiredMixin, CrudDeleteView):
+ class DeleteView(CrudDeleteView):
permission_required = permissoes_adm()
@@ -603,18 +603,18 @@ class TramitacaoAdmCrud(MasterDetailCrud):
list_field_names = ['data_tramitacao', 'unidade_tramitacao_local',
'unidade_tramitacao_destino', 'status']
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
form_class = TramitacaoAdmForm
permission_required = permissoes_adm()
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
form_class = TramitacaoAdmEditForm
permission_required = permissoes_adm()
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_adm()
- class ListView(PermissionRequiredMixin, MasterDetailCrud.ListView):
+ class ListView(MasterDetailCrud.ListView):
permission_required = permissoes_adm()
def get_queryset(self):
@@ -632,7 +632,7 @@ class TramitacaoAdmCrud(MasterDetailCrud):
perms = self.get_permission_required()
return self.request.user.has_perms(perms)
- class DetailView(PermissionRequiredMixin, MasterDetailCrud.DetailView):
+ class DetailView(MasterDetailCrud.DetailView):
permission_required = permissoes_adm()
def has_permission(self):
diff --git a/sapl/sessao/views.py b/sapl/sessao/views.py
index 8a500b2cb..d950488cf 100644
--- a/sapl/sessao/views.py
+++ b/sapl/sessao/views.py
@@ -1,8 +1,8 @@
from datetime import datetime
from re import sub
+from braces.views import PermissionRequiredMixin
from django.contrib import messages
-from django.contrib.auth.mixins import PermissionRequiredMixin
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.core.urlresolvers import reverse
from django.forms.utils import ErrorList
@@ -18,8 +18,7 @@ from rest_framework import generics
from sapl.crud.base import (Crud, CrudBaseMixin, CrudCreateView,
CrudDeleteView, CrudDetailView, CrudListView,
- CrudUpdateView, make_pagination)
-from sapl.crud.masterdetail import MasterDetailCrud
+ CrudUpdateView, make_pagination, MasterDetailCrud)
from sapl.materia.forms import pega_ultima_tramitacao
from sapl.materia.models import (Autoria, DocumentoAcessorio,
TipoMateriaLegislativa, Tramitacao)
@@ -43,6 +42,7 @@ from .models import (Bancada, Bloco, CargoBancada, CargoMesa,
SessaoPlenariaPresenca, TipoExpediente,
TipoResultadoVotacao, TipoSessaoPlenaria, VotoParlamentar)
+
OrdemDiaCrud = Crud.build(OrdemDia, '')
RegistroVotacaoCrud = Crud.build(RegistroVotacao, '')
@@ -77,7 +77,7 @@ class BlocoCrud(Crud):
model = Bloco
help_path = ''
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
list_field_names = ['nome', 'data_criacao', 'partidos']
def has_permission(self):
@@ -88,7 +88,7 @@ class BancadaCrud(Crud):
model = Bancada
help_path = ''
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
list_field_names = ['nome', 'legislatura']
def has_permission(self):
@@ -108,7 +108,8 @@ class TipoSessaoCrud(Crud):
model = TipoSessaoPlenaria
help_path = 'tipo_sessao_plenaria'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
+
def has_permission(self):
return permissao_tb_aux(self)
@@ -117,7 +118,8 @@ class TipoResultadoVotacaoCrud(Crud):
model = TipoResultadoVotacao
help_path = 'tipo_resultado_votacao'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
+
def has_permission(self):
return permissao_tb_aux(self)
@@ -126,7 +128,8 @@ class TipoExpedienteCrud(Crud):
model = TipoExpediente
help_path = 'tipo_expediente'
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
+
def has_permission(self):
return permissao_tb_aux(self)
@@ -135,7 +138,8 @@ class CargoBancadaCrud(Crud):
model = CargoBancada
help_path = ''
- class BaseMixin(PermissionRequiredMixin, CrudBaseMixin):
+ class BaseMixin(CrudBaseMixin):
+
def has_permission(self):
return permissao_tb_aux(self)
@@ -198,6 +202,7 @@ class MateriaOrdemDiaCrud(MasterDetailCrud):
return self.initial
class DetailView(MasterDetailCrud.DetailView):
+
@property
def layout_key(self):
return 'OrdemDiaDetail'
@@ -370,7 +375,7 @@ class ExpedienteMateriaCrud(MasterDetailCrud):
obj.resultado)
return [self._as_row(obj) for obj in object_list]
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
form_class = ExpedienteMateriaForm
permission_required = permissoes_sessao()
@@ -378,7 +383,7 @@ class ExpedienteMateriaCrud(MasterDetailCrud):
return reverse('sapl.sessao:expedientemateria_list',
kwargs={'pk': self.kwargs['pk']})
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
form_class = ExpedienteMateriaForm
permission_required = permissoes_sessao()
@@ -406,20 +411,20 @@ class OradorCrud(MasterDetailCrud):
class ListView(MasterDetailCrud.ListView):
ordering = ['numero_ordem', 'parlamentar']
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
permission_required = permissoes_sessao()
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
permission_required = permissoes_sessao()
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_sessao()
class OradorExpedienteCrud(OradorCrud):
model = OradorExpediente
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
permission_required = permissoes_sessao()
form_class = OradorExpedienteForm
@@ -427,18 +432,18 @@ class OradorExpedienteCrud(OradorCrud):
return reverse('sapl.sessao:oradorexpediente_list',
kwargs={'pk': self.kwargs['pk']})
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
permission_required = permissoes_sessao()
form_class = OradorExpedienteForm
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_sessao()
class OradorCrud(OradorCrud):
model = Orador
- class CreateView(PermissionRequiredMixin, MasterDetailCrud.CreateView):
+ class CreateView(MasterDetailCrud.CreateView):
permission_required = permissoes_sessao()
form_class = OradorForm
@@ -446,11 +451,11 @@ class OradorCrud(OradorCrud):
return reverse('sapl.sessao:orador_list',
kwargs={'pk': self.kwargs['pk']})
- class UpdateView(PermissionRequiredMixin, MasterDetailCrud.UpdateView):
+ class UpdateView(MasterDetailCrud.UpdateView):
permission_required = permissoes_sessao()
form_class = OradorForm
- class DeleteView(PermissionRequiredMixin, MasterDetailCrud.DeleteView):
+ class DeleteView(MasterDetailCrud.DeleteView):
permission_required = permissoes_sessao()
@@ -483,7 +488,7 @@ class SessaoCrud(Crud):
class ListView(CrudListView):
ordering = ['-data_inicio']
- class CreateView(PermissionRequiredMixin, CrudCreateView):
+ class CreateView(CrudCreateView):
permission_required = permissoes_sessao()
def get_initial(self):
@@ -493,10 +498,10 @@ class SessaoCrud(Crud):
return {'legislatura': legislatura,
'sessao_legislativa': sessao_legislativa}
- class UpdateView(PermissionRequiredMixin, CrudUpdateView):
+ class UpdateView(CrudUpdateView):
permission_required = permissoes_sessao()
- class DeleteView(PermissionRequiredMixin, CrudDeleteView):
+ class DeleteView(CrudDeleteView):
permission_required = permissoes_sessao()
@@ -2118,11 +2123,11 @@ class PesquisarPautaSessaoView(PesquisarSessaoPlenariaView):
def filtra_tramitacao_ordem_dia():
- lista = pega_ultima_tramitacao()
- return Tramitacao.objects.filter(
- id__in=lista,
- status__descricao='Ordem do Dia').distinct().values_list(
- 'materia_id', flat=True)
+ lista = pega_ultima_tramitacao()
+ return Tramitacao.objects.filter(
+ id__in=lista,
+ status__descricao='Ordem do Dia').distinct().values_list(
+ 'materia_id', flat=True)
def retira_materias_ja_adicionadas(id_sessao, model):
diff --git a/sapl/static/styles/app.scss b/sapl/static/styles/app.scss
index 114d4052d..2492724ed 100644
--- a/sapl/static/styles/app.scss
+++ b/sapl/static/styles/app.scss
@@ -70,6 +70,13 @@ h6, .h6 {
color: inherit;
}
+.caret {
+ /* Por padrão caret aponta para baixo*/
+ &.top {
+ transform: rotate(180deg);
+ }
+}
+
// #### CRUD DETAIL ########################################
p.control-label {
font-weight: bold;
diff --git a/sapl/templates/base.html b/sapl/templates/base.html
index 24c3af670..1367ab816 100644
--- a/sapl/templates/base.html
+++ b/sapl/templates/base.html
@@ -103,11 +103,11 @@
- {% if user|ver_menu_sistema_perm %}
-
+ {% if perms.base.menu_sistemas %}
+
Sistema