from math import ceil
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.core.urlresolvers import reverse, reverse_lazy
from django.utils import formats
from django.utils.translation import ugettext as _
import rtyaml
def heads_and_tails(list_of_lists):
for alist in list_of_lists:
yield alist[0], alist[1:]
def to_column(name_span):
fieldname, span = name_span
return Div(fieldname, css_class='col-md-%d' % span)
def to_row(names_spans):
return Div(*map(to_column, names_spans), css_class='row')
def to_fieldsets(fields):
for field in fields:
if isinstance(field, list):
legend, row_specs = field[0], field[1:]
rows = [to_row(name_span_list) for name_span_list in row_specs]
yield Fieldset(legend, *rows)
else:
yield field
def form_actions(more=[Div(css_class='clearfix')],
label=_('Salvar'), name='salvar',
css_class='float-right', disabled=True):
if disabled:
doubleclick = 'this.form.submit();this.disabled=true;'
else:
doubleclick = 'return true;'
return FormActions(
*more,
Submit(name, label, css_class=css_class,
# para impedir resubmissão do form
onclick=doubleclick),
css_class='form-group row justify-content-between'
)
class SaplFormHelper(FormHelper):
render_hidden_fields = True # default = False
"""
até a release 1.6.1 do django-crispy-forms, os fields em Meta.Fields eram
renderizados mesmo se não mencionados no helper.
Com esta mudança (https://github.com/django-crispy-forms/django-crispy-forms/commit/6b93e8a362422db8fe54aa731319c7cbc39990ba)
render_hidden_fields foi adicionado uma condição em que a cada
instância do Helper, fosse decidido se os fields não mencionados serião ou
não renderizados...
O Sapl até este commit: https://github.com/interlegis/sapl/commit/22b87f36ebc8659a6ecaf8831ab0f425206b0993
utilizou o django-crispy-forms na versão 1.6.1, ou seja,
sem a condição render_hidden_fields o que fazia o FormHelper, na 1.6.1
set comportar como se, agora, na 1.7.2 o default fosse True.
Como todos os Forms do Sapl foram construídos assumindo que fields
não incluídos explicitamente no Helper, o helper o incluiria implicitamente,
e assim o era, de acordo com commit acima do django-crispy-forms, então
cria-se essa classe:
class SaplFormHelper(FormHelper):
render_hidden_fields = True
onde torna o default, antes False, agora = True, o esperado pelos forms do sapl,
e substituí-se todos os FormHelper por SaplFormHelper dentro do projeto Sapl
esta explicação ficará aqui dentro do código, via commit, e na issue #2456.
"""
class SaplFormLayout(Layout):
def __init__(self, *fields, cancel_label=_('Cancelar'),
save_label=_('Salvar'), actions=None):
buttons = actions
if not buttons:
buttons = form_actions(label=save_label, more=[
HTML('%s' % cancel_label)
if cancel_label else None])
_fields = list(to_fieldsets(fields))
if buttons:
_fields += [to_row([(buttons, 12)])]
super(SaplFormLayout, self).__init__(*_fields)
def get_field_display(obj, fieldname):
field = ''
try:
field = obj._meta.get_field(fieldname)
except Exception as e:
""" nos casos que o fieldname não é um field_model,
ele pode ser um aggregate, annotate, um property, um manager,
ou mesmo uma método no model.
"""
value = getattr(obj, fieldname)
try:
verbose_name = value.model._meta.verbose_name
except AttributeError:
verbose_name = ''
else:
verbose_name = str(field.verbose_name)\
if hasattr(field, 'verbose_name') else ''
if hasattr(field, 'choices') and field.choices:
value = getattr(obj, 'get_%s_display' % fieldname)()
else:
value = getattr(obj, fieldname)
str_type_from_value = str(type(value))
str_type_from_field = str(type(field))
if value is None:
display = ''
elif '.date' in str_type_from_value:
display = formats.date_format(value, "SHORT_DATE_FORMAT")
elif 'bool' in str_type_from_value:
display = _('Sim') if value else _('Não')
elif 'ImageFieldFile' in str(type(value)):
if value:
display = ''.format(value.url)
else:
display = ''
elif 'FieldFile' in str_type_from_value:
if value:
display = '{}'.format(
value.url,
value.name.split('/')[-1:][0])
else:
display = ''
elif 'ManyRelatedManager' in str_type_from_value\
or 'RelatedManager' in str_type_from_value\
or 'GenericRelatedObjectManager' in str_type_from_value:
display = '