We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Formatar mudança de linha nos campos text do crud
As mudanças de linha `\n` dos campos TextField, ao que parece, estão sendo exibidas nas telas de leitura do crud.

Por exemplo no campo `observacao` de `DocumentoAdministrativo`.

--- 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, reverse_lazy
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=[Div(css_class='clearfix')],
38                  label=_('Salvar'), name='salvar', css_class='pull-right', disabled=True):
39 
40     if disabled:
41         doubleclick = 'this.form.submit();this.disabled=true;'
42     else:
43         doubleclick = 'return true;'
44 
45     return FormActions(
46         Submit(name, label, css_class=css_class,
47                # para impedir resubmissão do form
48                onclick=doubleclick),
49         *more)
50 
51 
52 class SaplFormLayout(Layout):
53 
54     def __init__(self, *fields, cancel_label=_('Cancelar'),
55                  save_label=_('Salvar'), actions=None):
56 
57         buttons = actions
58         if not buttons:
59             buttons = form_actions(label=save_label, more=[
60                 HTML('<a href="{{ view.cancel_url }}"'
61                      ' class="btn btn-inverse">%s</a>' % cancel_label)
62                 if cancel_label else None])
63 
64         _fields = list(to_fieldsets(fields))
65         if buttons:
66             _fields += [to_row([(buttons, 12)])]
67         super(SaplFormLayout, self).__init__(*_fields)
68 
69 
70 def get_field_display(obj, fieldname):
71     field = ''
72     try:
73         field = obj._meta.get_field(fieldname)
74     except Exception as e:
75         """ nos casos que o fieldname não é um field_model,
76             ele pode ser um aggregate, annotate, um property, um manager,
77             ou mesmo uma método no model.
78         """
79         value = getattr(obj, fieldname)
80         try:
81             verbose_name = value.model._meta.verbose_name
82         except AttributeError:
83             verbose_name = ''
84 
85     else:
86         verbose_name = str(field.verbose_name)\
87             if hasattr(field, 'verbose_name') else ''
88 
89         if hasattr(field, 'choices') and field.choices:
90             value = getattr(obj, 'get_%s_display' % fieldname)()
91         else:
92             value = getattr(obj, fieldname)
93 
94     str_type_from_value = str(type(value))
95     str_type_from_field = str(type(field))
96 
97     if value is None:
98         display = ''
99     elif '.date' in str_type_from_value:
100         display = formats.date_format(value, "SHORT_DATE_FORMAT")
101     elif 'bool' in str_type_from_value:
102         display = _('Sim') if value else _('Não')
103     elif 'ImageFieldFile' in str(type(value)):
104         if value:
105             display = '<img src="{}" />'.format(value.url)
106         else:
107             display = ''
108     elif 'FieldFile' in str_type_from_value:
109         if value:
110             display = '<a href="{}">{}</a>'.format(
111                 value.url,
112                 value.name.split('/')[-1:][0])
113         else:
114             display = ''
115     elif 'ManyRelatedManager' in str_type_from_value\
116             or 'RelatedManager' in str_type_from_value\
117             or 'GenericRelatedObjectManager' in str_type_from_value:
118         display = '<ul>'
119         for v in value.all():
120             display += '<li>%s</li>' % str(v)
121         display += '</ul>'
122         if not verbose_name:
123             if hasattr(field, 'related_model'):
124                 verbose_name = str(
125                     field.related_model._meta.verbose_name_plural)
126             elif hasattr(field, 'model'):
127                 verbose_name = str(field.model._meta.verbose_name_plural)
128     elif 'GenericForeignKey' in str_type_from_field:
129         display = '<a href="{}">{}</a>'.format(
130             reverse(
131                 '%s:%s_detail' % (
132                     value._meta.app_config.name, obj.content_type.model),
133                 args=(value.id,)),
134             value)
135     else:
136         display = str(value)
137     return verbose_name, display
138 
139 
140 class CrispyLayoutFormMixin:
141 
142     @property
143     def layout_key(self):
144         if hasattr(super(CrispyLayoutFormMixin, self), 'layout_key'):
145             return super(CrispyLayoutFormMixin, self).layout_key
146         else:
147             return self.model.__name__
148 
149     @property
150     def layout_key_set(self):
151         if hasattr(super(CrispyLayoutFormMixin, self), 'layout_key_set'):
152             return super(CrispyLayoutFormMixin, self).layout_key_set
153         else:
154             obj = self.crud if hasattr(self, 'crud') else self
155             return getattr(obj.model,
156                            obj.model_set).field.model.__name__
157 
158     def get_layout(self):
159         yaml_layout = '%s/layouts.yaml' % self.model._meta.app_config.label
160         return read_layout_from_yaml(yaml_layout, self.layout_key)
161 
162     def get_layout_set(self):
163         obj = self.crud if hasattr(self, 'crud') else self
164         yaml_layout = '%s/layouts.yaml' % getattr(
165             obj.model, obj.model_set).field.model._meta.app_config.label
166         return read_layout_from_yaml(yaml_layout, self.layout_key_set)
167 
168     @property
169     def fields(self):
170         if hasattr(self, 'form_class') and self.form_class:
171             return None
172         else:
173             '''Returns all fields in the layout'''
174             return [fieldname for legend_rows in self.get_layout()
175                     for row in legend_rows[1:]
176                     for fieldname, span in row]
177 
178     def get_form(self, form_class=None):
179         try:
180             form = super(CrispyLayoutFormMixin, self).get_form(form_class)
181         except AttributeError:
182             # simply return None if there is no get_form on super
183             pass
184         else:
185             if self.layout_key:
186                 form.helper = FormHelper()
187                 form.helper.layout = SaplFormLayout(*self.get_layout())
188             return form
189 
190     @property
191     def list_field_names(self):
192         '''The list of field names to display on table
193 
194         This base implementation returns the field names
195         in the first fieldset of the layout.
196         '''
197         obj = self.crud if hasattr(self, 'crud') else self
198         if hasattr(obj, 'list_field_names') and obj.list_field_names:
199             return obj.list_field_names
200         rows = self.get_layout()[0][1:]
201         return [fieldname for row in rows for fieldname, __ in row]
202 
203     @property
204     def list_field_names_set(self):
205         '''The list of field names to display on table
206 
207         This base implementation returns the field names
208         in the first fieldset of the layout.
209         '''
210         rows = self.get_layout_set()[0][1:]
211         return [fieldname for row in rows for fieldname, __ in row]
212 
213     def get_column(self, fieldname, span):
214         obj = self.get_object()
215 
216         func = None
217         if '|' in fieldname:
218             fieldname, func = tuple(fieldname.split('|'))
219 
220         if func:
221             verbose_name, text = getattr(self, func)(obj, fieldname)
222         else:
223             verbose_name, text = get_field_display(obj, fieldname)
224 
225         return {
226             'id': fieldname,
227             'span': span,
228             'verbose_name': verbose_name,
229             'text': text,
230         }
231 
232     def fk_urlize_for_detail(self, obj, fieldname):
233 
234         field = obj._meta.get_field(fieldname)
235         value = getattr(obj, fieldname)
236 
237         display = '<a href="{}">{}</a>'.format(
238             reverse(
239                 '%s:%s_detail' % (
240                     value._meta.app_config.name, value._meta.model_name),
241                 args=(value.id,)),
242             value)
243 
244         return field.verbose_name, display
245 
246     def m2m_urlize_for_detail(self, obj, fieldname):
247 
248         manager, fieldname = tuple(fieldname.split('__'))
249 
250         manager = getattr(obj, manager)
251 
252         verbose_name = manager.model._meta.verbose_name
253         display = ''
254         for item in manager.all():
255             obj_m2m = getattr(item, fieldname)
256 
257             if obj == obj_m2m:
258                 continue
259 
260             verbose_name = item._meta.get_field(fieldname).verbose_name
261 
262             display += '<li><a href="{}">{}</a></li>'.format(
263                 reverse(
264                     '%s:%s_detail' % (
265                         obj_m2m._meta.app_config.name, obj_m2m._meta.model_name),
266                     args=(obj_m2m.id,)),
267                 obj_m2m)
268 
269         display += ''
270 
271         if display:
272             display = '<ul>%s</ul>' % display
273         else:
274             verbose_name = ''
275 
276         return verbose_name, display
277 
278     @property
279     def layout_display(self):
280 
281         return [
282             {'legend': legend,
283              'rows': [[self.get_column(fieldname, span)
284                        for fieldname, span in row]
285                       for row in rows]
286              } for legend, rows in heads_and_tails(self.get_layout())]
287 
288 
289 def read_yaml_from_file(yaml_layout):
290     # TODO cache this at application level
291     t = template.loader.get_template(yaml_layout)
292     # aqui é importante converter para str pois, dependendo do ambiente,
293     # o rtyaml pode usar yaml.CSafeLoader, que exige str ou stream
294     rendered = str(t.render())
295     return rtyaml.load(rendered)
296 
297 
298 def read_layout_from_yaml(yaml_layout, key):
299     # TODO cache this at application level
300     yaml = read_yaml_from_file(yaml_layout)
301     base = yaml[key]
302 
303     def line_to_namespans(line):
304         split = [cell.split(':') for cell in line.split()]
305         namespans = [[s[0], int(s[1]) if len(s) > 1 else 0] for s in split]
306         remaining = 12 - sum(s for n, s in namespans)
307         nondefined = [ns for ns in namespans if not ns[1]]
308         while nondefined:
309             span = ceil(remaining / len(nondefined))
310             namespan = nondefined.pop(0)
311             namespan[1] = span
312             remaining = remaining - span
313         return list(map(tuple, namespans))
314 
315     return [[legend] + [line_to_namespans(l) for l in lines]
316             for legend, lines in base.items()]
317
```
--- 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
@@ -132,6 +132,8 @@
                     value._meta.app_config.name, obj.content_type.model),
                 args=(value.id,)),
             value)
+    elif 'TextField' in str_type_from_field:
+        display = value.replace('\n', '<br/>')
     else:
         display = str(value)
     return verbose_name, display

{"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@@ -132,6 +132,8 @@\n                     value._meta.app_config.name, obj.content_type.model),\n                 args=(value.id,)),\n             value)\n+    elif 'TextField' in str_type_from_field:\n+        display = value.replace('\\n', '<br/>')\n     else:\n         display = str(value)\n     return verbose_name, display\n", "issue": "Formatar mudan\u00e7a de linha nos campos text do crud\nAs mudan\u00e7as de linha `\\n` dos campos TextField, ao que parece, est\u00e3o sendo exibidas nas telas de leitura do crud.\r\n\r\nPor exemplo no campo `observacao` de `DocumentoAdministrativo`.\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, reverse_lazy\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=[Div(css_class='clearfix')],\n                 label=_('Salvar'), name='salvar', css_class='pull-right', disabled=True):\n\n    if disabled:\n        doubleclick = 'this.form.submit();this.disabled=true;'\n    else:\n        doubleclick = 'return true;'\n\n    return FormActions(\n        Submit(name, label, css_class=css_class,\n               # para impedir resubmiss\u00e3o do form\n               onclick=doubleclick),\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(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\n        func = None\n        if '|' in fieldname:\n            fieldname, func = tuple(fieldname.split('|'))\n\n        if func:\n            verbose_name, text = getattr(self, func)(obj, fieldname)\n        else:\n            verbose_name, text = get_field_display(obj, fieldname)\n\n        return {\n            'id': fieldname,\n            'span': span,\n            'verbose_name': verbose_name,\n            'text': text,\n        }\n\n    def fk_urlize_for_detail(self, obj, fieldname):\n\n        field = obj._meta.get_field(fieldname)\n        value = getattr(obj, fieldname)\n\n        display = '<a href=\"{}\">{}</a>'.format(\n            reverse(\n                '%s:%s_detail' % (\n                    value._meta.app_config.name, value._meta.model_name),\n                args=(value.id,)),\n            value)\n\n        return field.verbose_name, display\n\n    def m2m_urlize_for_detail(self, obj, fieldname):\n\n        manager, fieldname = tuple(fieldname.split('__'))\n\n        manager = getattr(obj, manager)\n\n        verbose_name = manager.model._meta.verbose_name\n        display = ''\n        for item in manager.all():\n            obj_m2m = getattr(item, fieldname)\n\n            if obj == obj_m2m:\n                continue\n\n            verbose_name = item._meta.get_field(fieldname).verbose_name\n\n            display += '<li><a href=\"{}\">{}</a></li>'.format(\n                reverse(\n                    '%s:%s_detail' % (\n                        obj_m2m._meta.app_config.name, obj_m2m._meta.model_name),\n                    args=(obj_m2m.id,)),\n                obj_m2m)\n\n        display += ''\n\n        if display:\n            display = '<ul>%s</ul>' % display\n        else:\n            verbose_name = ''\n\n        return verbose_name, display\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, reverse_lazy\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=[Div(css_class='clearfix')],\n                 label=_('Salvar'), name='salvar', css_class='pull-right', disabled=True):\n\n    if disabled:\n        doubleclick = 'this.form.submit();this.disabled=true;'\n    else:\n        doubleclick = 'return true;'\n\n    return FormActions(\n        Submit(name, label, css_class=css_class,\n               # para impedir resubmiss\u00e3o do form\n               onclick=doubleclick),\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(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    elif 'TextField' in str_type_from_field:\n        display = value.replace('\\n', '<br/>')\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\n        func = None\n        if '|' in fieldname:\n            fieldname, func = tuple(fieldname.split('|'))\n\n        if func:\n            verbose_name, text = getattr(self, func)(obj, fieldname)\n        else:\n            verbose_name, text = get_field_display(obj, fieldname)\n\n        return {\n            'id': fieldname,\n            'span': span,\n            'verbose_name': verbose_name,\n            'text': text,\n        }\n\n    def fk_urlize_for_detail(self, obj, fieldname):\n\n        field = obj._meta.get_field(fieldname)\n        value = getattr(obj, fieldname)\n\n        display = '<a href=\"{}\">{}</a>'.format(\n            reverse(\n                '%s:%s_detail' % (\n                    value._meta.app_config.name, value._meta.model_name),\n                args=(value.id,)),\n            value)\n\n        return field.verbose_name, display\n\n    def m2m_urlize_for_detail(self, obj, fieldname):\n\n        manager, fieldname = tuple(fieldname.split('__'))\n\n        manager = getattr(obj, manager)\n\n        verbose_name = manager.model._meta.verbose_name\n        display = ''\n        for item in manager.all():\n            obj_m2m = getattr(item, fieldname)\n\n            if obj == obj_m2m:\n                continue\n\n            verbose_name = item._meta.get_field(fieldname).verbose_name\n\n            display += '<li><a href=\"{}\">{}</a></li>'.format(\n                reverse(\n                    '%s:%s_detail' % (\n                        obj_m2m._meta.app_config.name, obj_m2m._meta.model_name),\n                    args=(obj_m2m.id,)),\n                obj_m2m)\n\n        display += ''\n\n        if display:\n            display = '<ul>%s</ul>' % display\n        else:\n            verbose_name = ''\n\n        return verbose_name, display\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"}]}