Skip to content

Commit ff0cb11

Browse files
committed
[1.2.X] Fixed #13599 -- No longer embed hidden <td> elements in ChangeList that cause improper rendering when list_editable is enabled; refactored admin_changelist tests. Thanks, skevy for bug report and patch.
Backport of r13744 from trunk. git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@13745 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 8829b7d commit ff0cb11

File tree

4 files changed

+45
-17
lines changed

4 files changed

+45
-17
lines changed

django/contrib/admin/media/css/changelists.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
width: 100%;
1010
}
1111

12+
.change-list .hiddenfields { display:none; }
13+
1214
.change-list .filtered table {
1315
border-right: 1px solid #ddd;
1416
}

django/contrib/admin/templates/admin/change_list_results.html

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
{% if result_hidden_fields %}
2+
<div class="hiddenfields"> {# DIV for HTML validation #}
3+
{% for item in result_hidden_fields %}{{ item }}{% endfor %}
4+
</div>
5+
{% endif %}
16
{% if results %}
27
<table cellspacing="0" id="result_list">
38
<thead>

django/contrib/admin/templatetags/admin_list.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ def items_for_result(cl, result, form):
189189
else:
190190
result_repr = conditional_escape(result_repr)
191191
yield mark_safe(u'<td%s>%s</td>' % (row_class, result_repr))
192-
if form:
192+
if form and not form[cl.model._meta.pk.name].is_hidden:
193193
yield mark_safe(u'<td>%s</td>' % force_unicode(form[cl.model._meta.pk.name]))
194194

195195
def results(cl):
@@ -200,11 +200,18 @@ def results(cl):
200200
for res in cl.result_list:
201201
yield list(items_for_result(cl, res, None))
202202

203+
def result_hidden_fields(cl):
204+
if cl.formset:
205+
for res, form in zip(cl.result_list, cl.formset.forms):
206+
if form[cl.model._meta.pk.name].is_hidden:
207+
yield mark_safe(force_unicode(form[cl.model._meta.pk.name]))
208+
203209
def result_list(cl):
204210
"""
205211
Displays the headers and data list together
206212
"""
207213
return {'cl': cl,
214+
'result_hidden_fields': list(result_hidden_fields(cl)),
208215
'result_headers': list(result_headers(cl)),
209216
'results': list(results(cl))}
210217
result_list = register.inclusion_tag("admin/change_list_results.html")(result_list)

tests/regressiontests/admin_changelist/tests.py

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import unittest
21
from django.contrib import admin
32
from django.contrib.admin.views.main import ChangeList
43
from django.template import Context, Template
4+
from django.test import TransactionTestCase
55
from regressiontests.admin_changelist.models import Child, Parent
66

7-
class ChangeListTests(unittest.TestCase):
7+
class ChangeListTests(TransactionTestCase):
88
def test_select_related_preserved(self):
99
"""
1010
Regression test for #10348: ChangeList.get_query_set() shouldn't
@@ -18,9 +18,8 @@ def test_select_related_preserved(self):
1818

1919
def test_result_list_html(self):
2020
"""
21-
Regression test for #11791: Inclusion tag result_list generates a
22-
table and this checks that the items are nested within the table
23-
element tags.
21+
Verifies that inclusion tag result_list generates a table when with
22+
default ModelAdmin settings.
2423
"""
2524
new_parent = Parent.objects.create(name='parent')
2625
new_child = Child.objects.create(name='name', parent=new_parent)
@@ -29,16 +28,27 @@ def test_result_list_html(self):
2928
cl = ChangeList(request, Child, m.list_display, m.list_display_links,
3029
m.list_filter, m.date_hierarchy, m.search_fields,
3130
m.list_select_related, m.list_per_page, m.list_editable, m)
32-
FormSet = m.get_changelist_formset(request)
33-
cl.formset = FormSet(queryset=cl.result_list)
31+
cl.formset = None
3432
template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}')
3533
context = Context({'cl': cl})
3634
table_output = template.render(context)
37-
hidden_input_elem = '<input type="hidden" name="form-0-id" value="1" id="id_form-0-id" />'
38-
self.failIf(table_output.find(hidden_input_elem) == -1,
39-
'Failed to find expected hidden input element in: %s' % table_output)
40-
self.failIf(table_output.find('<td>%s</td>' % hidden_input_elem) == -1,
41-
'Hidden input element is not enclosed in <td> element.')
35+
row_html = '<tbody><tr class="row1"><td><input type="checkbox" class="action-select" value="1" name="_selected_action" /></td><th><a href="1/">name</a></th><td>Parent object</td></tr></tbody>'
36+
self.failIf(table_output.find(row_html) == -1,
37+
'Failed to find expected row element: %s' % table_output)
38+
39+
def test_result_list_editable_html(self):
40+
"""
41+
Regression tests for #11791: Inclusion tag result_list generates a
42+
table and this checks that the items are nested within the table
43+
element tags.
44+
Also a regression test for #13599, verifies that hidden fields
45+
when list_editable is enabled are rendered in a div outside the
46+
table.
47+
"""
48+
new_parent = Parent.objects.create(name='parent')
49+
new_child = Child.objects.create(name='name', parent=new_parent)
50+
request = MockRequest()
51+
m = ChildAdmin(Child, admin.site)
4252

4353
# Test with list_editable fields
4454
m.list_display = ['id', 'name', 'parent']
@@ -52,10 +62,14 @@ def test_result_list_html(self):
5262
template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}')
5363
context = Context({'cl': cl})
5464
table_output = template.render(context)
55-
self.failIf(table_output.find(hidden_input_elem) == -1,
56-
'Failed to find expected hidden input element in: %s' % table_output)
57-
self.failIf(table_output.find('<td>%s</td>' % hidden_input_elem) == -1,
58-
'Hidden input element is not enclosed in <td> element.')
65+
# make sure that hidden fields are in the correct place
66+
hiddenfields_div = '<div class="hiddenfields"><input type="hidden" name="form-0-id" value="1" id="id_form-0-id" /></div>'
67+
self.failIf(table_output.find(hiddenfields_div) == -1,
68+
'Failed to find hidden fields in: %s' % table_output)
69+
# make sure that list editable fields are rendered in divs correctly
70+
editable_name_field = '<input name="form-0-name" value="name" class="vTextField" maxlength="30" type="text" id="id_form-0-name" />'
71+
self.failIf('<td>%s</td>' % editable_name_field == -1,
72+
'Failed to find "name" list_editable field in: %s' % table_output)
5973

6074
class ChildAdmin(admin.ModelAdmin):
6175
list_display = ['name', 'parent']

0 commit comments

Comments
 (0)