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.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@13744 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Justin Bronn 2010-09-11 03:01:07 +00:00
parent 1efa807703
commit 04f50c1f28
4 changed files with 45 additions and 17 deletions

View File

@ -9,6 +9,8 @@
width: 100%; width: 100%;
} }
.change-list .hiddenfields { display:none; }
.change-list .filtered table { .change-list .filtered table {
border-right: 1px solid #ddd; border-right: 1px solid #ddd;
} }

View File

@ -1,3 +1,8 @@
{% if result_hidden_fields %}
<div class="hiddenfields"> {# DIV for HTML validation #}
{% for item in result_hidden_fields %}{{ item }}{% endfor %}
</div>
{% endif %}
{% if results %} {% if results %}
<div class="results"> <div class="results">
<table cellspacing="0" id="result_list"> <table cellspacing="0" id="result_list">

View File

@ -189,7 +189,7 @@ def items_for_result(cl, result, form):
else: else:
result_repr = conditional_escape(result_repr) result_repr = conditional_escape(result_repr)
yield mark_safe(u'<td%s>%s</td>' % (row_class, result_repr)) yield mark_safe(u'<td%s>%s</td>' % (row_class, result_repr))
if form: if form and not form[cl.model._meta.pk.name].is_hidden:
yield mark_safe(u'<td>%s</td>' % force_unicode(form[cl.model._meta.pk.name])) yield mark_safe(u'<td>%s</td>' % force_unicode(form[cl.model._meta.pk.name]))
def results(cl): def results(cl):
@ -200,11 +200,18 @@ def results(cl):
for res in cl.result_list: for res in cl.result_list:
yield list(items_for_result(cl, res, None)) yield list(items_for_result(cl, res, None))
def result_hidden_fields(cl):
if cl.formset:
for res, form in zip(cl.result_list, cl.formset.forms):
if form[cl.model._meta.pk.name].is_hidden:
yield mark_safe(force_unicode(form[cl.model._meta.pk.name]))
def result_list(cl): def result_list(cl):
""" """
Displays the headers and data list together Displays the headers and data list together
""" """
return {'cl': cl, return {'cl': cl,
'result_hidden_fields': list(result_hidden_fields(cl)),
'result_headers': list(result_headers(cl)), 'result_headers': list(result_headers(cl)),
'results': list(results(cl))} 'results': list(results(cl))}
result_list = register.inclusion_tag("admin/change_list_results.html")(result_list) result_list = register.inclusion_tag("admin/change_list_results.html")(result_list)

View File

@ -1,10 +1,10 @@
import unittest
from django.contrib import admin from django.contrib import admin
from django.contrib.admin.views.main import ChangeList from django.contrib.admin.views.main import ChangeList
from django.template import Context, Template from django.template import Context, Template
from django.test import TransactionTestCase
from regressiontests.admin_changelist.models import Child, Parent from regressiontests.admin_changelist.models import Child, Parent
class ChangeListTests(unittest.TestCase): class ChangeListTests(TransactionTestCase):
def test_select_related_preserved(self): def test_select_related_preserved(self):
""" """
Regression test for #10348: ChangeList.get_query_set() shouldn't Regression test for #10348: ChangeList.get_query_set() shouldn't
@ -18,9 +18,8 @@ class ChangeListTests(unittest.TestCase):
def test_result_list_html(self): def test_result_list_html(self):
""" """
Regression test for #11791: Inclusion tag result_list generates a Verifies that inclusion tag result_list generates a table when with
table and this checks that the items are nested within the table default ModelAdmin settings.
element tags.
""" """
new_parent = Parent.objects.create(name='parent') new_parent = Parent.objects.create(name='parent')
new_child = Child.objects.create(name='name', parent=new_parent) new_child = Child.objects.create(name='name', parent=new_parent)
@ -29,16 +28,27 @@ class ChangeListTests(unittest.TestCase):
cl = ChangeList(request, Child, m.list_display, m.list_display_links, cl = ChangeList(request, Child, m.list_display, m.list_display_links,
m.list_filter, m.date_hierarchy, m.search_fields, m.list_filter, m.date_hierarchy, m.search_fields,
m.list_select_related, m.list_per_page, m.list_editable, m) m.list_select_related, m.list_per_page, m.list_editable, m)
FormSet = m.get_changelist_formset(request) cl.formset = None
cl.formset = FormSet(queryset=cl.result_list)
template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}') template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}')
context = Context({'cl': cl}) context = Context({'cl': cl})
table_output = template.render(context) table_output = template.render(context)
hidden_input_elem = '<input type="hidden" name="form-0-id" value="1" id="id_form-0-id" />' 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>'
self.failIf(table_output.find(hidden_input_elem) == -1, self.failIf(table_output.find(row_html) == -1,
'Failed to find expected hidden input element in: %s' % table_output) 'Failed to find expected row element: %s' % table_output)
self.failIf(table_output.find('<td>%s</td>' % hidden_input_elem) == -1,
'Hidden input element is not enclosed in <td> element.') def test_result_list_editable_html(self):
"""
Regression tests for #11791: Inclusion tag result_list generates a
table and this checks that the items are nested within the table
element tags.
Also a regression test for #13599, verifies that hidden fields
when list_editable is enabled are rendered in a div outside the
table.
"""
new_parent = Parent.objects.create(name='parent')
new_child = Child.objects.create(name='name', parent=new_parent)
request = MockRequest()
m = ChildAdmin(Child, admin.site)
# Test with list_editable fields # Test with list_editable fields
m.list_display = ['id', 'name', 'parent'] m.list_display = ['id', 'name', 'parent']
@ -52,10 +62,14 @@ class ChangeListTests(unittest.TestCase):
template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}') template = Template('{% load admin_list %}{% spaceless %}{% result_list cl %}{% endspaceless %}')
context = Context({'cl': cl}) context = Context({'cl': cl})
table_output = template.render(context) table_output = template.render(context)
self.failIf(table_output.find(hidden_input_elem) == -1, # make sure that hidden fields are in the correct place
'Failed to find expected hidden input element in: %s' % table_output) hiddenfields_div = '<div class="hiddenfields"><input type="hidden" name="form-0-id" value="1" id="id_form-0-id" /></div>'
self.failIf(table_output.find('<td>%s</td>' % hidden_input_elem) == -1, self.failIf(table_output.find(hiddenfields_div) == -1,
'Hidden input element is not enclosed in <td> element.') 'Failed to find hidden fields in: %s' % table_output)
# make sure that list editable fields are rendered in divs correctly
editable_name_field = '<input name="form-0-name" value="name" class="vTextField" maxlength="30" type="text" id="id_form-0-name" />'
self.failIf('<td>%s</td>' % editable_name_field == -1,
'Failed to find "name" list_editable field in: %s' % table_output)
class ChildAdmin(admin.ModelAdmin): class ChildAdmin(admin.ModelAdmin):
list_display = ['name', 'parent'] list_display = ['name', 'parent']