Browse Source

Add general table implementation to crud list

pull/6/head
Marcio Mazza 10 years ago
parent
commit
06d7442553
  1. 33
      sapl/crud.py
  2. 58
      sapl/test_crud.py
  3. 0
      sapl/teststubs/__init__.py
  4. 22
      sapl/teststubs/urls_for_list_test.py
  5. 30
      templates/crud/list.html

33
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

58
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):

0
sapl/teststubs/__init__.py

22
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)),
]

30
templates/crud/list.html

@ -10,25 +10,35 @@
</a></dd>
</dl>
{% if not field_values %}
<p>{{ NO_ENTRIES_MSG }}</p>
{% else %}
<table class="table table-hover">
<thead>
<tr>
<th>{% trans 'Id' %}</th>
<th>{% trans 'Nome' %}</th>
<th>{% trans 'Sigla' %}</th>
<th>{% trans 'Tipo' %}</th>
{% for name in field_names %}
<th>{{ name }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for comissao in object_list %}
<td>{{ comissao.id }}</td>
<td>{{ comissao.nome }}</td>
<td>{{ comissao.sigla }}</td>
<td>{{ comissao.tipo }}</td>
{% for value_list in field_values %}
<tr>
{% for value, href in value_list %}
<td>
{% if href %}
<a href="{{ href }}">{{ value }}</a>
{% else %}
{{ value }}
{% endif %}
</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
{% if is_paginated %}
<div class="pagination-centered">
@ -43,7 +53,7 @@
<li class="arrow unavailable" aria-disabled="true"><a href="">&laquo;</a></li>
{% endif %}
{% for page in custom_page_range %}
{% for page in page_range %}
{% if page %}
<li {% if page == page_obj.number %}class="current"{% endif %}>
<a href="?page={{ page }}">{{ page }}</a>

Loading…
Cancel
Save