[1.5.x] Fixed #8627 -- Prevented textareas to swallow first newline content

Browsers consider the first newline in textareas as some display
artifact, not real content. Hence they are not sending it back to
the server. If we want to keep initial newlines, we have to add one
when we render the textarea.
Thanks bastih for the report and initial patch.

Backport of 78f66691ee from master.
This commit is contained in:
Claude Paroz 2012-11-05 20:27:06 +01:00
parent c7d5e7c75b
commit a23c9c48a8
7 changed files with 52 additions and 3 deletions

View File

@ -403,7 +403,7 @@ class Textarea(Widget):
def render(self, name, value, attrs=None): def render(self, name, value, attrs=None):
if value is None: value = '' if value is None: value = ''
final_attrs = self.build_attrs(attrs, name=name) final_attrs = self.build_attrs(attrs, name=name)
return format_html('<textarea{0}>{1}</textarea>', return format_html('<textarea{0}>\r\n{1}</textarea>',
flatatt(final_attrs), flatatt(final_attrs),
force_text(value)) force_text(value))

View File

@ -84,3 +84,7 @@ class Group(models.Model):
class Cheese(models.Model): class Cheese(models.Model):
name = models.CharField(max_length=100) name = models.CharField(max_length=100)
class Article(models.Model):
content = models.TextField()

View File

@ -0,0 +1,8 @@
<html>
<body>
<form method="post" action=".">
{{ form.as_p }}<br>
<input id="submit" type="submit">
</form>
</body>
</html>

View File

@ -18,4 +18,4 @@ from .regressions import FormsRegressionsTestCase
from .util import FormsUtilTestCase from .util import FormsUtilTestCase
from .validators import TestFieldWithValidators from .validators import TestFieldWithValidators
from .widgets import (FormsWidgetTestCase, FormsI18NWidgetsTestCase, from .widgets import (FormsWidgetTestCase, FormsI18NWidgetsTestCase,
WidgetTests, ClearableFileInputTests) WidgetTests, LiveWidgetTests, ClearableFileInputTests)

View File

@ -4,7 +4,9 @@ from __future__ import unicode_literals
import copy import copy
import datetime import datetime
from django.contrib.admin.tests import AdminSeleniumWebDriverTestCase
from django.core.files.uploadedfile import SimpleUploadedFile from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.urlresolvers import reverse
from django.forms import * from django.forms import *
from django.forms.widgets import RadioFieldRenderer from django.forms.widgets import RadioFieldRenderer
from django.utils import formats from django.utils import formats
@ -15,6 +17,8 @@ from django.test import TestCase
from django.test.utils import override_settings from django.test.utils import override_settings
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
from ..models import Article
class FormsWidgetTestCase(TestCase): class FormsWidgetTestCase(TestCase):
# Each Widget class corresponds to an HTML form widget. A Widget knows how to # Each Widget class corresponds to an HTML form widget. A Widget knows how to
@ -1095,6 +1099,22 @@ class WidgetTests(TestCase):
self.assertFalse(form.is_valid()) self.assertFalse(form.is_valid())
class LiveWidgetTests(AdminSeleniumWebDriverTestCase):
urls = 'regressiontests.forms.urls'
def test_textarea_trailing_newlines(self):
"""
Test that a roundtrip on a ModelForm doesn't alter the TextField value
"""
article = Article.objects.create(content="\nTst\n")
self.selenium.get('%s%s' % (self.live_server_url,
reverse('article_form', args=[article.pk])))
self.selenium.find_element_by_id('submit').submit()
article = Article.objects.get(pk=article.pk)
# Should be "\nTst\n" after #19251 is fixed
self.assertEqual(article.content, "\r\nTst\r\n")
@python_2_unicode_compatible @python_2_unicode_compatible
class FakeFieldFile(object): class FakeFieldFile(object):
""" """

View File

@ -0,0 +1,9 @@
from django.conf.urls import patterns, url
from django.views.generic.edit import UpdateView
from .views import ArticleFormView
urlpatterns = patterns('',
url(r'^/model_form/(?P<pk>\d+)/$', ArticleFormView.as_view(), name="article_form"),
)

View File

@ -0,0 +1,8 @@
from django.views.generic.edit import UpdateView
from .models import Article
class ArticleFormView(UpdateView):
model = Article
success_url = '/'