From 06d74425538753b2884f2430058724b7080a2770 Mon Sep 17 00:00:00 2001 From: Marcio Mazza Date: Sun, 26 Jul 2015 17:32:23 -0300 Subject: [PATCH] Add general table implementation to crud list --- sapl/crud.py | 33 ++++++-- sapl/test_crud.py | 58 ++++++++++++- sapl/teststubs/__init__.py | 0 sapl/teststubs/urls_for_list_test.py | 22 +++++ templates/crud/list.html | 120 +++++++++++++++------------ 5 files changed, 167 insertions(+), 66 deletions(-) create mode 100644 sapl/teststubs/__init__.py create mode 100644 sapl/teststubs/urls_for_list_test.py diff --git a/sapl/crud.py b/sapl/crud.py index f67825f7b..d8338e13f 100644 --- a/sapl/crud.py +++ b/sapl/crud.py @@ -3,11 +3,15 @@ from crispy_forms.helper import FormHelper from django import forms from django.conf.urls import url from django.core.urlresolvers import reverse, reverse_lazy -from django.utils.translation import ugettext as _ +from django.utils.translation import ugettext_lazy as _ from django.views.generic import ( CreateView, DeleteView, ListView, UpdateView, DetailView) from sapl.layout import SaplFormLayout +from django.utils.functional import cached_property + + +NO_ENTRIES_MSG = _('Não existem registros') def from_to(start, end): @@ -114,8 +118,10 @@ def build_crud(model, *layout): class CrudListView(BaseMixin, ListView): title = BaseMixin.verbose_name_plural paginate_by = 10 + no_entries_msg = NO_ENTRIES_MSG - def get_fieldnames(self): + @cached_property + def field_names(self): '''The list of field names to display on table This base implementation returns the field names @@ -124,13 +130,24 @@ def build_crud(model, *layout): rows = layout[0][1:] return [fieldname for row in rows for fieldname, __ in row] + def get_field_values(self, object_list): + return [[(get_field_display(obj, name)[1], + obj.pk if i == 0 else None) + for i, name in enumerate(self.field_names)] + for obj in object_list + ] + def get_context_data(self, **kwargs): - context_data = super(CrudListView, self).get_context_data(**kwargs) - paginator = context_data['paginator'] - current_page = context_data['page_obj'] - context_data['custom_page_range'] = make_pagination( - current_page.number, paginator.num_pages) - return context_data + context = super(CrudListView, self).get_context_data(**kwargs) + paginator = context['paginator'] + page_obj = context['page_obj'] + context['page_range'] = make_pagination( + page_obj.number, paginator.num_pages) + object_list = context['object_list'] + context['field_names'] = self.field_names + context['field_values'] = self.get_field_values(object_list) + context['NO_ENTRIES_MSG'] = NO_ENTRIES_MSG + return context class CrudCreateView(BaseMixin, FormMessagesMixin, CreateView): form_class = crud.model_form diff --git a/sapl/test_crud.py b/sapl/test_crud.py index dbe5d2661..1fe62de99 100644 --- a/sapl/test_crud.py +++ b/sapl/test_crud.py @@ -3,7 +3,9 @@ from django.core.urlresolvers import reverse from model_mommy import mommy from comissoes.models import Comissao, TipoComissao -from .crud import get_field_display, build_crud, make_pagination, from_to +from .crud import (get_field_display, build_crud, make_pagination, from_to, + NO_ENTRIES_MSG) +from comissoes.views import comissao_crud pytestmark = pytest.mark.django_db @@ -24,7 +26,7 @@ pytestmark = pytest.mark.django_db def test_listview_get_fieldnames(layout, result): crud = build_crud(Comissao, *layout) view = crud.CrudListView() - assert view.get_fieldnames() == result + assert view.field_names == result __ = None # for test readability @@ -156,10 +158,13 @@ def assert_h1(res, title): assert res.html.find('h1').text == title +NO_ENTRIES_MSG = str(NO_ENTRIES_MSG) # "unlazy" + + def assert_on_list_page(res): assert_h1(res, 'Comissões') assert 'Adicionar Comissão' in res - assert res.html.find('table') + assert res.html.find('table') or NO_ENTRIES_MSG in res # XXX ... characterize better @@ -177,6 +182,53 @@ def assert_on_detail_page(res, stub_name): assert 'Excluir Comissão' in res +@pytest.mark.urls('sapl.teststubs.urls_for_list_test') +@pytest.mark.parametrize("num_entries, page_size, ranges, page_list", [ + (0, 6, [], []), + (5, 5, [], []), + (10, 5, [(0, 5), (5, 10)], ['«', '1', '2', '»']), + (9, 4, [(0, 4), (4, 8), (8, 9)], ['«', '1', '2', '3', '»']), +]) +def test_flux_list_paginate_detail( + app, monkeypatch, num_entries, page_size, ranges, page_list): + + entries_labels = [] + for i in range(num_entries): + nome, sigla, tipo = 'nome %s' % i, 'sigla %s' % i, 'tipo %s' % i, + entries_labels.append([nome, sigla, tipo]) + mommy.make(Comissao, nome=nome, sigla=sigla, tipo__nome=tipo) + + from .teststubs.urls_for_list_test import crud + crud.CrudListView.paginate_by = page_size + + res = app.get('/comissoes/') + assert_on_list_page(res) + + table = res.html.find('table') + paginator = res.html.find('ul', {'class': 'pagination'}) + + if num_entries == 0: + assert NO_ENTRIES_MSG in res + assert not table + assert not paginator + else: + def rows(): + header, *rows = table.findAll('tr') + assert header.text.strip().split() == ['nome', 'sigla', 'tipo'] + return [[td.text.strip() for td in tr.findAll('td')] + for tr in rows] + + if page_list: + assert paginator + assert paginator.text.strip().split() == page_list + + assert entries_labels[:page_size] == rows() + + # TODO... go to the second page and back + # TODO... go to detail page + + + @pytest.mark.parametrize("cancel, make_invalid_submit", [ (a, b) for a in (True, False) for b in (True, False)]) def test_flux_list_create_detail(app, cancel, make_invalid_submit): diff --git a/sapl/teststubs/__init__.py b/sapl/teststubs/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/sapl/teststubs/urls_for_list_test.py b/sapl/teststubs/urls_for_list_test.py new file mode 100644 index 000000000..07a76bd89 --- /dev/null +++ b/sapl/teststubs/urls_for_list_test.py @@ -0,0 +1,22 @@ +from django.conf.urls import include, url +from sapl.crud import build_crud + +from comissoes.models import Comissao + + +crud = build_crud( + Comissao, + + ['Dados Básicos', + [('nome', 9), ('sigla', 3)], + [('tipo', 3)] + ], + + ['Dados Complementares', + [('finalidade', 12)] + ], +) + +urlpatterns = [ + url(r'^comissoes/', include(crud.urls)), +] diff --git a/templates/crud/list.html b/templates/crud/list.html index 22fbd71a4..73d2d0ff3 100644 --- a/templates/crud/list.html +++ b/templates/crud/list.html @@ -3,66 +3,76 @@ {% block base_content %} - {# FIXME is this the best markup to use? #} - +{# FIXME is this the best markup to use? #} + +{% if not field_values %} +

{{ NO_ENTRIES_MSG }}

+{% else %} - - - - - - - - - - {% for comissao in object_list %} - - - - - - {% endfor %} - -
{% trans 'Id' %}{% trans 'Nome' %}{% trans 'Sigla' %}{% trans 'Tipo' %}
{{ comissao.id }}{{ comissao.nome }}{{ comissao.sigla }}{{ comissao.tipo }}
- - {% if is_paginated %} -
- +
{% endif %} {% endblock %}