From d345a030c2f3b332512e5091248dd8b06e859eac Mon Sep 17 00:00:00 2001
From: Claude Paroz <claude@2xlibre.net>
Date: Sat, 22 Mar 2014 17:00:50 +0100
Subject: [PATCH] [1.7.x] Fixed #22241 -- Selectively added line breaks in
 admin read-only fields

When content is supposed to contain HTML, we do not try to add
line breaks in read-only contents.
Thanks Alexander Todorov for the report.
Backport of c94bff2 from master.
---
 django/contrib/admin/helpers.py                          | 4 +++-
 .../admin/templates/admin/edit_inline/tabular.html       | 2 +-
 .../contrib/admin/templates/admin/includes/fieldset.html | 2 +-
 tests/admin_views/admin.py                               | 9 +++++++--
 tests/admin_views/tests.py                               | 1 +
 5 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py
index 50d089255b..bf80ac5d48 100644
--- a/django/contrib/admin/helpers.py
+++ b/django/contrib/admin/helpers.py
@@ -7,7 +7,7 @@ from django.contrib.admin.templatetags.admin_static import static
 from django.core.exceptions import ObjectDoesNotExist
 from django.db.models.fields.related import ManyToManyRel
 from django.forms.utils import flatatt
-from django.template.defaultfilters import capfirst
+from django.template.defaultfilters import capfirst, linebreaksbr
 from django.utils.encoding import force_text, smart_text
 from django.utils.html import conditional_escape, format_html
 from django.utils.safestring import mark_safe
@@ -182,6 +182,8 @@ class AdminReadonlyField(object):
                     result_repr = smart_text(value)
                     if getattr(attr, "allow_tags", False):
                         result_repr = mark_safe(result_repr)
+                    else:
+                        result_repr = linebreaksbr(result_repr)
             else:
                 if isinstance(f.rel, ManyToManyRel) and value is not None:
                     result_repr = ", ".join(map(six.text_type, value.all()))
diff --git a/django/contrib/admin/templates/admin/edit_inline/tabular.html b/django/contrib/admin/templates/admin/edit_inline/tabular.html
index 2a3463280d..9ef6e8f1d5 100644
--- a/django/contrib/admin/templates/admin/edit_inline/tabular.html
+++ b/django/contrib/admin/templates/admin/edit_inline/tabular.html
@@ -47,7 +47,7 @@
               {% if not field.field.is_hidden %}
               <td{% if field.field.name %} class="field-{{ field.field.name }}"{% endif %}>
               {% if field.is_readonly %}
-                  <p>{{ field.contents|linebreaksbr }}</p>
+                  <p>{{ field.contents }}</p>
               {% else %}
                   {{ field.field.errors.as_ul }}
                   {{ field.field }}
diff --git a/django/contrib/admin/templates/admin/includes/fieldset.html b/django/contrib/admin/templates/admin/includes/fieldset.html
index f38564c5af..c45e731faf 100644
--- a/django/contrib/admin/templates/admin/includes/fieldset.html
+++ b/django/contrib/admin/templates/admin/includes/fieldset.html
@@ -14,7 +14,7 @@
                     {% else %}
                         {{ field.label_tag }}
                         {% if field.is_readonly %}
-                            <p>{{ field.contents|linebreaksbr }}</p>
+                            <p>{{ field.contents }}</p>
                         {% else %}
                             {{ field.field }}
                         {% endif %}
diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py
index e9c6d4dc4c..a392daf293 100644
--- a/tests/admin_views/admin.py
+++ b/tests/admin_views/admin.py
@@ -15,6 +15,7 @@ from django.conf.urls import patterns, url
 from django.forms.models import BaseModelFormSet
 from django.http import HttpResponse, StreamingHttpResponse
 from django.contrib.admin import BooleanFieldListFilter
+from django.utils.safestring import mark_safe
 from django.utils.six import StringIO
 
 from .models import (Article, Chapter, Child, Parent, Picture, Widget,
@@ -407,8 +408,8 @@ class PrePopulatedPostAdmin(admin.ModelAdmin):
 class PostAdmin(admin.ModelAdmin):
     list_display = ['title', 'public']
     readonly_fields = (
-        'posted', 'awesomeness_level', 'coolness', 'value', 'multiline',
-        lambda obj: "foo"
+        'posted', 'awesomeness_level', 'coolness', 'value',
+        'multiline', 'multiline_html', lambda obj: "foo"
     )
 
     inlines = [
@@ -427,6 +428,10 @@ class PostAdmin(admin.ModelAdmin):
     def multiline(self, instance):
         return "Multiline\ntest\nstring"
 
+    def multiline_html(self, instance):
+        return mark_safe("Multiline<br>\nhtml<br>\ncontent")
+    multiline_html.allow_tags = True
+
     value.short_description = 'Value in $US'
 
 
diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py
index c39e99aa1b..a88117fa6f 100644
--- a/tests/admin_views/tests.py
+++ b/tests/admin_views/tests.py
@@ -3622,6 +3622,7 @@ class ReadonlyTest(TestCase):
 
         # Checks that multiline text in a readonly field gets <br /> tags
         self.assertContains(response, "Multiline<br />test<br />string")
+        self.assertContains(response, "<p>Multiline<br />html<br />content</p>", html=True)
         self.assertContains(response, "InlineMultiline<br />test<br />string")
 
         self.assertContains(response,