We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Pesquisa matérias legislativas
Ao preencher alguns dados no form de pesquisa de matéria legislativa e clicar em pesquisar, ocorre o seguinte:
No chrome o botão desabilita e a seta do mouse vira um sinal de proibido
no firefox ocorre o mesmo, porem mostra resultados

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sapl/crispy_layout_mixin.py`
Content:
```
1 from math import ceil
2 
3 import rtyaml
4 from crispy_forms.bootstrap import FormActions
5 from crispy_forms.helper import FormHelper
6 from crispy_forms.layout import HTML, Div, Fieldset, Layout, Submit
7 from django import template
8 from django.core.urlresolvers import reverse
9 from django.utils import formats
10 from django.utils.translation import ugettext as _
11 
12 
13 def heads_and_tails(list_of_lists):
14     for alist in list_of_lists:
15         yield alist[0], alist[1:]
16 
17 
18 def to_column(name_span):
19     fieldname, span = name_span
20     return Div(fieldname, css_class='col-md-%d' % span)
21 
22 
23 def to_row(names_spans):
24     return Div(*map(to_column, names_spans), css_class='row-fluid')
25 
26 
27 def to_fieldsets(fields):
28     for field in fields:
29         if isinstance(field, list):
30             legend, row_specs = field[0], field[1:]
31             rows = [to_row(name_span_list) for name_span_list in row_specs]
32             yield Fieldset(legend, *rows)
33         else:
34             yield field
35 
36 
37 def form_actions(more=[], save_label=_('Salvar')):
38     return FormActions(
39         Submit('salvar', save_label, css_class='pull-right',
40                # para impedir resubmissão do form
41                onclick='this.disabled=true;'),
42         *more)
43 
44 
45 class SaplFormLayout(Layout):
46 
47     def __init__(self, *fields, cancel_label=_('Cancelar'),
48                  save_label=_('Salvar'), actions=None):
49 
50         buttons = actions
51         if not buttons:
52             buttons = form_actions(save_label=save_label, more=[
53                 HTML('<a href="{{ view.cancel_url }}"'
54                      ' class="btn btn-inverse">%s</a>' % cancel_label)
55                 if cancel_label else None])
56 
57         _fields = list(to_fieldsets(fields))
58         if buttons:
59             _fields += [to_row([(buttons, 12)])]
60         super(SaplFormLayout, self).__init__(*_fields)
61 
62 
63 def get_field_display(obj, fieldname):
64     field = ''
65     try:
66         field = obj._meta.get_field(fieldname)
67     except Exception as e:
68         """ nos casos que o fieldname não é um field_model,
69             ele pode ser um aggregate, annotate, um property, um manager,
70             ou mesmo uma método no model.
71         """
72         value = getattr(obj, fieldname)
73         try:
74             verbose_name = value.model._meta.verbose_name
75         except AttributeError:
76             verbose_name = ''
77 
78     else:
79         verbose_name = str(field.verbose_name)\
80             if hasattr(field, 'verbose_name') else ''
81 
82         if hasattr(field, 'choices') and field.choices:
83             value = getattr(obj, 'get_%s_display' % fieldname)()
84         else:
85             value = getattr(obj, fieldname)
86 
87     str_type_from_value = str(type(value))
88     str_type_from_field = str(type(field))
89 
90     if value is None:
91         display = ''
92     elif 'date' in str_type_from_value:
93         display = formats.date_format(value, "SHORT_DATE_FORMAT")
94     elif 'bool' in str_type_from_value:
95         display = _('Sim') if value else _('Não')
96     elif 'ImageFieldFile' in str(type(value)):
97         if value:
98             display = '<img src="{}" />'.format(value.url)
99         else:
100             display = ''
101     elif 'FieldFile' in str_type_from_value:
102         if value:
103             display = '<a href="{}">{}</a>'.format(
104                 value.url,
105                 value.name.split('/')[-1:][0])
106         else:
107             display = ''
108     elif 'ManyRelatedManager' in str_type_from_value\
109             or 'RelatedManager' in str_type_from_value\
110             or 'GenericRelatedObjectManager' in str_type_from_value:
111         display = '<ul>'
112         for v in value.all():
113             display += '<li>%s</li>' % str(v)
114         display += '</ul>'
115         if not verbose_name:
116             if hasattr(field, 'related_model'):
117                 verbose_name = str(
118                     field.related_model._meta.verbose_name_plural)
119             elif hasattr(field, 'model'):
120                 verbose_name = str(field.model._meta.verbose_name_plural)
121     elif 'GenericForeignKey' in str_type_from_field:
122         display = '<a href="{}">{}</a>'.format(
123             reverse(
124                 '%s:%s_detail' % (
125                     value._meta.app_config.name, obj.content_type.model),
126                 args=(value.id,)),
127             value)
128     else:
129         display = str(value)
130     return verbose_name, display
131 
132 
133 class CrispyLayoutFormMixin:
134 
135     @property
136     def layout_key(self):
137         if hasattr(super(CrispyLayoutFormMixin, self), 'layout_key'):
138             return super(CrispyLayoutFormMixin, self).layout_key
139         else:
140             return self.model.__name__
141 
142     @property
143     def layout_key_set(self):
144         if hasattr(super(CrispyLayoutFormMixin, self), 'layout_key_set'):
145             return super(CrispyLayoutFormMixin, self).layout_key_set
146         else:
147             obj = self.crud if hasattr(self, 'crud') else self
148             return getattr(obj.model,
149                            obj.model_set).field.model.__name__
150 
151     def get_layout(self):
152         yaml_layout = '%s/layouts.yaml' % self.model._meta.app_config.label
153         return read_layout_from_yaml(yaml_layout, self.layout_key)
154 
155     def get_layout_set(self):
156         obj = self.crud if hasattr(self, 'crud') else self
157         yaml_layout = '%s/layouts.yaml' % getattr(
158             obj.model, obj.model_set).field.model._meta.app_config.label
159         return read_layout_from_yaml(yaml_layout, self.layout_key_set)
160 
161     @property
162     def fields(self):
163         if hasattr(self, 'form_class') and self.form_class:
164             return None
165         else:
166             '''Returns all fields in the layout'''
167             return [fieldname for legend_rows in self.get_layout()
168                     for row in legend_rows[1:]
169                     for fieldname, span in row]
170 
171     def get_form(self, form_class=None):
172         try:
173             form = super(CrispyLayoutFormMixin, self).get_form(form_class)
174         except AttributeError:
175             # simply return None if there is no get_form on super
176             pass
177         else:
178             if self.layout_key:
179                 form.helper = FormHelper()
180                 form.helper.layout = SaplFormLayout(*self.get_layout())
181             return form
182 
183     @property
184     def list_field_names(self):
185         '''The list of field names to display on table
186 
187         This base implementation returns the field names
188         in the first fieldset of the layout.
189         '''
190         obj = self.crud if hasattr(self, 'crud') else self
191         if hasattr(obj, 'list_field_names') and obj.list_field_names:
192             return obj.list_field_names
193         rows = self.get_layout()[0][1:]
194         return [fieldname for row in rows for fieldname, __ in row]
195 
196     @property
197     def list_field_names_set(self):
198         '''The list of field names to display on table
199 
200         This base implementation returns the field names
201         in the first fieldset of the layout.
202         '''
203         rows = self.get_layout_set()[0][1:]
204         return [fieldname for row in rows for fieldname, __ in row]
205 
206     def get_column(self, fieldname, span):
207         obj = self.get_object()
208         verbose_name, text = get_field_display(obj, fieldname)
209         return {
210             'id': fieldname,
211             'span': span,
212             'verbose_name': verbose_name,
213             'text': text,
214         }
215 
216     @property
217     def layout_display(self):
218 
219         return [
220             {'legend': legend,
221              'rows': [[self.get_column(fieldname, span)
222                        for fieldname, span in row]
223                       for row in rows]
224              } for legend, rows in heads_and_tails(self.get_layout())]
225 
226 
227 def read_yaml_from_file(yaml_layout):
228     # TODO cache this at application level
229     t = template.loader.get_template(yaml_layout)
230     # aqui é importante converter para str pois, dependendo do ambiente,
231     # o rtyaml pode usar yaml.CSafeLoader, que exige str ou stream
232     rendered = str(t.render())
233     return rtyaml.load(rendered)
234 
235 
236 def read_layout_from_yaml(yaml_layout, key):
237     # TODO cache this at application level
238     yaml = read_yaml_from_file(yaml_layout)
239     base = yaml[key]
240 
241     def line_to_namespans(line):
242         split = [cell.split(':') for cell in line.split()]
243         namespans = [[s[0], int(s[1]) if len(s) > 1 else 0] for s in split]
244         remaining = 12 - sum(s for n, s in namespans)
245         nondefined = [ns for ns in namespans if not ns[1]]
246         while nondefined:
247             span = ceil(remaining / len(nondefined))
248             namespan = nondefined.pop(0)
249             namespan[1] = span
250             remaining = remaining - span
251         return list(map(tuple, namespans))
252 
253     return [[legend] + [line_to_namespans(l) for l in lines]
254             for legend, lines in base.items()]
255
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/sapl/crispy_layout_mixin.py b/sapl/crispy_layout_mixin.py
--- a/sapl/crispy_layout_mixin.py
+++ b/sapl/crispy_layout_mixin.py
@@ -38,7 +38,7 @@
     return FormActions(
         Submit('salvar', save_label, css_class='pull-right',
                # para impedir resubmissão do form
-               onclick='this.disabled=true;'),
+               onclick='this.form.submit();this.disabled=true;'),
         *more)

{"golden_diff": "diff --git a/sapl/crispy_layout_mixin.py b/sapl/crispy_layout_mixin.py\n--- a/sapl/crispy_layout_mixin.py\n+++ b/sapl/crispy_layout_mixin.py\n@@ -38,7 +38,7 @@\n     return FormActions(\n         Submit('salvar', save_label, css_class='pull-right',\n                # para impedir resubmiss\u00e3o do form\n-               onclick='this.disabled=true;'),\n+               onclick='this.form.submit();this.disabled=true;'),\n         *more)\n", "issue": "Pesquisa mat\u00e9rias legislativas\nAo preencher alguns dados no form de pesquisa de mat\u00e9ria legislativa e clicar em pesquisar, ocorre o seguinte:\r\nNo chrome o bot\u00e3o desabilita e a seta do mouse vira um sinal de proibido\r\nno firefox ocorre o mesmo, porem mostra resultados\n", "before_files": [{"content": "from math import ceil\n\nimport rtyaml\nfrom crispy_forms.bootstrap import FormActions\nfrom crispy_forms.helper import FormHelper\nfrom crispy_forms.layout import HTML, Div, Fieldset, Layout, Submit\nfrom django import template\nfrom django.core.urlresolvers import reverse\nfrom django.utils import formats\nfrom django.utils.translation import ugettext as _\n\n\ndef heads_and_tails(list_of_lists):\n    for alist in list_of_lists:\n        yield alist[0], alist[1:]\n\n\ndef to_column(name_span):\n    fieldname, span = name_span\n    return Div(fieldname, css_class='col-md-%d' % span)\n\n\ndef to_row(names_spans):\n    return Div(*map(to_column, names_spans), css_class='row-fluid')\n\n\ndef to_fieldsets(fields):\n    for field in fields:\n        if isinstance(field, list):\n            legend, row_specs = field[0], field[1:]\n            rows = [to_row(name_span_list) for name_span_list in row_specs]\n            yield Fieldset(legend, *rows)\n        else:\n            yield field\n\n\ndef form_actions(more=[], save_label=_('Salvar')):\n    return FormActions(\n        Submit('salvar', save_label, css_class='pull-right',\n               # para impedir resubmiss\u00e3o do form\n               onclick='this.disabled=true;'),\n        *more)\n\n\nclass SaplFormLayout(Layout):\n\n    def __init__(self, *fields, cancel_label=_('Cancelar'),\n                 save_label=_('Salvar'), actions=None):\n\n        buttons = actions\n        if not buttons:\n            buttons = form_actions(save_label=save_label, more=[\n                HTML('<a href=\"{{ view.cancel_url }}\"'\n                     ' class=\"btn btn-inverse\">%s</a>' % cancel_label)\n                if cancel_label else None])\n\n        _fields = list(to_fieldsets(fields))\n        if buttons:\n            _fields += [to_row([(buttons, 12)])]\n        super(SaplFormLayout, self).__init__(*_fields)\n\n\ndef get_field_display(obj, fieldname):\n    field = ''\n    try:\n        field = obj._meta.get_field(fieldname)\n    except Exception as e:\n        \"\"\" nos casos que o fieldname n\u00e3o \u00e9 um field_model,\n            ele pode ser um aggregate, annotate, um property, um manager,\n            ou mesmo uma m\u00e9todo no model.\n        \"\"\"\n        value = getattr(obj, fieldname)\n        try:\n            verbose_name = value.model._meta.verbose_name\n        except AttributeError:\n            verbose_name = ''\n\n    else:\n        verbose_name = str(field.verbose_name)\\\n            if hasattr(field, 'verbose_name') else ''\n\n        if hasattr(field, 'choices') and field.choices:\n            value = getattr(obj, 'get_%s_display' % fieldname)()\n        else:\n            value = getattr(obj, fieldname)\n\n    str_type_from_value = str(type(value))\n    str_type_from_field = str(type(field))\n\n    if value is None:\n        display = ''\n    elif 'date' in str_type_from_value:\n        display = formats.date_format(value, \"SHORT_DATE_FORMAT\")\n    elif 'bool' in str_type_from_value:\n        display = _('Sim') if value else _('N\u00e3o')\n    elif 'ImageFieldFile' in str(type(value)):\n        if value:\n            display = '<img src=\"{}\" />'.format(value.url)\n        else:\n            display = ''\n    elif 'FieldFile' in str_type_from_value:\n        if value:\n            display = '<a href=\"{}\">{}</a>'.format(\n                value.url,\n                value.name.split('/')[-1:][0])\n        else:\n            display = ''\n    elif 'ManyRelatedManager' in str_type_from_value\\\n            or 'RelatedManager' in str_type_from_value\\\n            or 'GenericRelatedObjectManager' in str_type_from_value:\n        display = '<ul>'\n        for v in value.all():\n            display += '<li>%s</li>' % str(v)\n        display += '</ul>'\n        if not verbose_name:\n            if hasattr(field, 'related_model'):\n                verbose_name = str(\n                    field.related_model._meta.verbose_name_plural)\n            elif hasattr(field, 'model'):\n                verbose_name = str(field.model._meta.verbose_name_plural)\n    elif 'GenericForeignKey' in str_type_from_field:\n        display = '<a href=\"{}\">{}</a>'.format(\n            reverse(\n                '%s:%s_detail' % (\n                    value._meta.app_config.name, obj.content_type.model),\n                args=(value.id,)),\n            value)\n    else:\n        display = str(value)\n    return verbose_name, display\n\n\nclass CrispyLayoutFormMixin:\n\n    @property\n    def layout_key(self):\n        if hasattr(super(CrispyLayoutFormMixin, self), 'layout_key'):\n            return super(CrispyLayoutFormMixin, self).layout_key\n        else:\n            return self.model.__name__\n\n    @property\n    def layout_key_set(self):\n        if hasattr(super(CrispyLayoutFormMixin, self), 'layout_key_set'):\n            return super(CrispyLayoutFormMixin, self).layout_key_set\n        else:\n            obj = self.crud if hasattr(self, 'crud') else self\n            return getattr(obj.model,\n                           obj.model_set).field.model.__name__\n\n    def get_layout(self):\n        yaml_layout = '%s/layouts.yaml' % self.model._meta.app_config.label\n        return read_layout_from_yaml(yaml_layout, self.layout_key)\n\n    def get_layout_set(self):\n        obj = self.crud if hasattr(self, 'crud') else self\n        yaml_layout = '%s/layouts.yaml' % getattr(\n            obj.model, obj.model_set).field.model._meta.app_config.label\n        return read_layout_from_yaml(yaml_layout, self.layout_key_set)\n\n    @property\n    def fields(self):\n        if hasattr(self, 'form_class') and self.form_class:\n            return None\n        else:\n            '''Returns all fields in the layout'''\n            return [fieldname for legend_rows in self.get_layout()\n                    for row in legend_rows[1:]\n                    for fieldname, span in row]\n\n    def get_form(self, form_class=None):\n        try:\n            form = super(CrispyLayoutFormMixin, self).get_form(form_class)\n        except AttributeError:\n            # simply return None if there is no get_form on super\n            pass\n        else:\n            if self.layout_key:\n                form.helper = FormHelper()\n                form.helper.layout = SaplFormLayout(*self.get_layout())\n            return form\n\n    @property\n    def list_field_names(self):\n        '''The list of field names to display on table\n\n        This base implementation returns the field names\n        in the first fieldset of the layout.\n        '''\n        obj = self.crud if hasattr(self, 'crud') else self\n        if hasattr(obj, 'list_field_names') and obj.list_field_names:\n            return obj.list_field_names\n        rows = self.get_layout()[0][1:]\n        return [fieldname for row in rows for fieldname, __ in row]\n\n    @property\n    def list_field_names_set(self):\n        '''The list of field names to display on table\n\n        This base implementation returns the field names\n        in the first fieldset of the layout.\n        '''\n        rows = self.get_layout_set()[0][1:]\n        return [fieldname for row in rows for fieldname, __ in row]\n\n    def get_column(self, fieldname, span):\n        obj = self.get_object()\n        verbose_name, text = get_field_display(obj, fieldname)\n        return {\n            'id': fieldname,\n            'span': span,\n            'verbose_name': verbose_name,\n            'text': text,\n        }\n\n    @property\n    def layout_display(self):\n\n        return [\n            {'legend': legend,\n             'rows': [[self.get_column(fieldname, span)\n                       for fieldname, span in row]\n                      for row in rows]\n             } for legend, rows in heads_and_tails(self.get_layout())]\n\n\ndef read_yaml_from_file(yaml_layout):\n    # TODO cache this at application level\n    t = template.loader.get_template(yaml_layout)\n    # aqui \u00e9 importante converter para str pois, dependendo do ambiente,\n    # o rtyaml pode usar yaml.CSafeLoader, que exige str ou stream\n    rendered = str(t.render())\n    return rtyaml.load(rendered)\n\n\ndef read_layout_from_yaml(yaml_layout, key):\n    # TODO cache this at application level\n    yaml = read_yaml_from_file(yaml_layout)\n    base = yaml[key]\n\n    def line_to_namespans(line):\n        split = [cell.split(':') for cell in line.split()]\n        namespans = [[s[0], int(s[1]) if len(s) > 1 else 0] for s in split]\n        remaining = 12 - sum(s for n, s in namespans)\n        nondefined = [ns for ns in namespans if not ns[1]]\n        while nondefined:\n            span = ceil(remaining / len(nondefined))\n            namespan = nondefined.pop(0)\n            namespan[1] = span\n            remaining = remaining - span\n        return list(map(tuple, namespans))\n\n    return [[legend] + [line_to_namespans(l) for l in lines]\n            for legend, lines in base.items()]\n", "path": "sapl/crispy_layout_mixin.py"}], "after_files": [{"content": "from math import ceil\n\nimport rtyaml\nfrom crispy_forms.bootstrap import FormActions\nfrom crispy_forms.helper import FormHelper\nfrom crispy_forms.layout import HTML, Div, Fieldset, Layout, Submit\nfrom django import template\nfrom django.core.urlresolvers import reverse\nfrom django.utils import formats\nfrom django.utils.translation import ugettext as _\n\n\ndef heads_and_tails(list_of_lists):\n    for alist in list_of_lists:\n        yield alist[0], alist[1:]\n\n\ndef to_column(name_span):\n    fieldname, span = name_span\n    return Div(fieldname, css_class='col-md-%d' % span)\n\n\ndef to_row(names_spans):\n    return Div(*map(to_column, names_spans), css_class='row-fluid')\n\n\ndef to_fieldsets(fields):\n    for field in fields:\n        if isinstance(field, list):\n            legend, row_specs = field[0], field[1:]\n            rows = [to_row(name_span_list) for name_span_list in row_specs]\n            yield Fieldset(legend, *rows)\n        else:\n            yield field\n\n\ndef form_actions(more=[], save_label=_('Salvar')):\n    return FormActions(\n        Submit('salvar', save_label, css_class='pull-right',\n               # para impedir resubmiss\u00e3o do form\n               onclick='this.form.submit();this.disabled=true;'),\n        *more)\n\n\nclass SaplFormLayout(Layout):\n\n    def __init__(self, *fields, cancel_label=_('Cancelar'),\n                 save_label=_('Salvar'), actions=None):\n\n        buttons = actions\n        if not buttons:\n            buttons = form_actions(save_label=save_label, more=[\n                HTML('<a href=\"{{ view.cancel_url }}\"'\n                     ' class=\"btn btn-inverse\">%s</a>' % cancel_label)\n                if cancel_label else None])\n\n        _fields = list(to_fieldsets(fields))\n        if buttons:\n            _fields += [to_row([(buttons, 12)])]\n        super(SaplFormLayout, self).__init__(*_fields)\n\n\ndef get_field_display(obj, fieldname):\n    field = ''\n    try:\n        field = obj._meta.get_field(fieldname)\n    except Exception as e:\n        \"\"\" nos casos que o fieldname n\u00e3o \u00e9 um field_model,\n            ele pode ser um aggregate, annotate, um property, um manager,\n            ou mesmo uma m\u00e9todo no model.\n        \"\"\"\n        value = getattr(obj, fieldname)\n        try:\n            verbose_name = value.model._meta.verbose_name\n        except AttributeError:\n            verbose_name = ''\n\n    else:\n        verbose_name = str(field.verbose_name)\\\n            if hasattr(field, 'verbose_name') else ''\n\n        if hasattr(field, 'choices') and field.choices:\n            value = getattr(obj, 'get_%s_display' % fieldname)()\n        else:\n            value = getattr(obj, fieldname)\n\n    str_type_from_value = str(type(value))\n    str_type_from_field = str(type(field))\n\n    if value is None:\n        display = ''\n    elif 'date' in str_type_from_value:\n        display = formats.date_format(value, \"SHORT_DATE_FORMAT\")\n    elif 'bool' in str_type_from_value:\n        display = _('Sim') if value else _('N\u00e3o')\n    elif 'ImageFieldFile' in str(type(value)):\n        if value:\n            display = '<img src=\"{}\" />'.format(value.url)\n        else:\n            display = ''\n    elif 'FieldFile' in str_type_from_value:\n        if value:\n            display = '<a href=\"{}\">{}</a>'.format(\n                value.url,\n                value.name.split('/')[-1:][0])\n        else:\n            display = ''\n    elif 'ManyRelatedManager' in str_type_from_value\\\n            or 'RelatedManager' in str_type_from_value\\\n            or 'GenericRelatedObjectManager' in str_type_from_value:\n        display = '<ul>'\n        for v in value.all():\n            display += '<li>%s</li>' % str(v)\n        display += '</ul>'\n        if not verbose_name:\n            if hasattr(field, 'related_model'):\n                verbose_name = str(\n                    field.related_model._meta.verbose_name_plural)\n            elif hasattr(field, 'model'):\n                verbose_name = str(field.model._meta.verbose_name_plural)\n    elif 'GenericForeignKey' in str_type_from_field:\n        display = '<a href=\"{}\">{}</a>'.format(\n            reverse(\n                '%s:%s_detail' % (\n                    value._meta.app_config.name, obj.content_type.model),\n                args=(value.id,)),\n            value)\n    else:\n        display = str(value)\n    return verbose_name, display\n\n\nclass CrispyLayoutFormMixin:\n\n    @property\n    def layout_key(self):\n        if hasattr(super(CrispyLayoutFormMixin, self), 'layout_key'):\n            return super(CrispyLayoutFormMixin, self).layout_key\n        else:\n            return self.model.__name__\n\n    @property\n    def layout_key_set(self):\n        if hasattr(super(CrispyLayoutFormMixin, self), 'layout_key_set'):\n            return super(CrispyLayoutFormMixin, self).layout_key_set\n        else:\n            obj = self.crud if hasattr(self, 'crud') else self\n            return getattr(obj.model,\n                           obj.model_set).field.model.__name__\n\n    def get_layout(self):\n        yaml_layout = '%s/layouts.yaml' % self.model._meta.app_config.label\n        return read_layout_from_yaml(yaml_layout, self.layout_key)\n\n    def get_layout_set(self):\n        obj = self.crud if hasattr(self, 'crud') else self\n        yaml_layout = '%s/layouts.yaml' % getattr(\n            obj.model, obj.model_set).field.model._meta.app_config.label\n        return read_layout_from_yaml(yaml_layout, self.layout_key_set)\n\n    @property\n    def fields(self):\n        if hasattr(self, 'form_class') and self.form_class:\n            return None\n        else:\n            '''Returns all fields in the layout'''\n            return [fieldname for legend_rows in self.get_layout()\n                    for row in legend_rows[1:]\n                    for fieldname, span in row]\n\n    def get_form(self, form_class=None):\n        try:\n            form = super(CrispyLayoutFormMixin, self).get_form(form_class)\n        except AttributeError:\n            # simply return None if there is no get_form on super\n            pass\n        else:\n            if self.layout_key:\n                form.helper = FormHelper()\n                form.helper.layout = SaplFormLayout(*self.get_layout())\n            return form\n\n    @property\n    def list_field_names(self):\n        '''The list of field names to display on table\n\n        This base implementation returns the field names\n        in the first fieldset of the layout.\n        '''\n        obj = self.crud if hasattr(self, 'crud') else self\n        if hasattr(obj, 'list_field_names') and obj.list_field_names:\n            return obj.list_field_names\n        rows = self.get_layout()[0][1:]\n        return [fieldname for row in rows for fieldname, __ in row]\n\n    @property\n    def list_field_names_set(self):\n        '''The list of field names to display on table\n\n        This base implementation returns the field names\n        in the first fieldset of the layout.\n        '''\n        rows = self.get_layout_set()[0][1:]\n        return [fieldname for row in rows for fieldname, __ in row]\n\n    def get_column(self, fieldname, span):\n        obj = self.get_object()\n        verbose_name, text = get_field_display(obj, fieldname)\n        return {\n            'id': fieldname,\n            'span': span,\n            'verbose_name': verbose_name,\n            'text': text,\n        }\n\n    @property\n    def layout_display(self):\n\n        return [\n            {'legend': legend,\n             'rows': [[self.get_column(fieldname, span)\n                       for fieldname, span in row]\n                      for row in rows]\n             } for legend, rows in heads_and_tails(self.get_layout())]\n\n\ndef read_yaml_from_file(yaml_layout):\n    # TODO cache this at application level\n    t = template.loader.get_template(yaml_layout)\n    # aqui \u00e9 importante converter para str pois, dependendo do ambiente,\n    # o rtyaml pode usar yaml.CSafeLoader, que exige str ou stream\n    rendered = str(t.render())\n    return rtyaml.load(rendered)\n\n\ndef read_layout_from_yaml(yaml_layout, key):\n    # TODO cache this at application level\n    yaml = read_yaml_from_file(yaml_layout)\n    base = yaml[key]\n\n    def line_to_namespans(line):\n        split = [cell.split(':') for cell in line.split()]\n        namespans = [[s[0], int(s[1]) if len(s) > 1 else 0] for s in split]\n        remaining = 12 - sum(s for n, s in namespans)\n        nondefined = [ns for ns in namespans if not ns[1]]\n        while nondefined:\n            span = ceil(remaining / len(nondefined))\n            namespan = nondefined.pop(0)\n            namespan[1] = span\n            remaining = remaining - span\n        return list(map(tuple, namespans))\n\n    return [[legend] + [line_to_namespans(l) for l in lines]\n            for legend, lines in base.items()]\n", "path": "sapl/crispy_layout_mixin.py"}]}