Fixed #20934 -- Avoided NoReverseMatch in ModelAdmin.changelist_view
The view tried to display links to a ModelAdmin's change_view, which resulted in NoReverseMatches if get_urls was overridden to remove the corresponding url.
This commit is contained in:
parent
6af05e7a0f
commit
65cf82bd08
|
@ -9,6 +9,7 @@ from django.contrib.admin.views.main import (ALL_VAR, EMPTY_CHANGELIST_VALUE,
|
||||||
ORDER_VAR, PAGE_VAR, SEARCH_VAR)
|
ORDER_VAR, PAGE_VAR, SEARCH_VAR)
|
||||||
from django.contrib.admin.templatetags.admin_static import static
|
from django.contrib.admin.templatetags.admin_static import static
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
from django.core.urlresolvers import NoReverseMatch
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import formats
|
from django.utils import formats
|
||||||
from django.utils.html import escapejs, format_html
|
from django.utils.html import escapejs, format_html
|
||||||
|
@ -216,25 +217,36 @@ def items_for_result(cl, result, form):
|
||||||
row_class = mark_safe(' class="%s"' % ' '.join(row_classes))
|
row_class = mark_safe(' class="%s"' % ' '.join(row_classes))
|
||||||
# If list_display_links not defined, add the link tag to the first field
|
# If list_display_links not defined, add the link tag to the first field
|
||||||
if (first and not cl.list_display_links) or field_name in cl.list_display_links:
|
if (first and not cl.list_display_links) or field_name in cl.list_display_links:
|
||||||
table_tag = {True:'th', False:'td'}[first]
|
table_tag = 'th' if first else 'td'
|
||||||
first = False
|
first = False
|
||||||
url = cl.url_for_result(result)
|
|
||||||
url = add_preserved_filters({'preserved_filters': cl.preserved_filters, 'opts': cl.opts}, url)
|
# Display link to the result's change_view if the url exists, else
|
||||||
# Convert the pk to something that can be used in Javascript.
|
# display just the result's representation.
|
||||||
# Problem cases are long ints (23L) and non-ASCII strings.
|
try:
|
||||||
if cl.to_field:
|
url = cl.url_for_result(result)
|
||||||
attr = str(cl.to_field)
|
except NoReverseMatch:
|
||||||
|
link_or_text = result_repr
|
||||||
else:
|
else:
|
||||||
attr = pk
|
url = add_preserved_filters({'preserved_filters': cl.preserved_filters, 'opts': cl.opts}, url)
|
||||||
value = result.serializable_value(attr)
|
# Convert the pk to something that can be used in Javascript.
|
||||||
result_id = escapejs(value)
|
# Problem cases are long ints (23L) and non-ASCII strings.
|
||||||
yield format_html('<{0}{1}><a href="{2}"{3}>{4}</a></{5}>',
|
if cl.to_field:
|
||||||
|
attr = str(cl.to_field)
|
||||||
|
else:
|
||||||
|
attr = pk
|
||||||
|
value = result.serializable_value(attr)
|
||||||
|
result_id = escapejs(value)
|
||||||
|
link_or_text = format_html(
|
||||||
|
'<a href="{0}"{1}>{2}</a>',
|
||||||
|
url,
|
||||||
|
format_html(' onclick="opener.dismissRelatedLookupPopup(window, '{0}'); return false;"', result_id)
|
||||||
|
if cl.is_popup else '',
|
||||||
|
result_repr)
|
||||||
|
|
||||||
|
yield format_html('<{0}{1}>{2}</{3}>',
|
||||||
table_tag,
|
table_tag,
|
||||||
row_class,
|
row_class,
|
||||||
url,
|
link_or_text,
|
||||||
format_html(' onclick="opener.dismissRelatedLookupPopup(window, '{0}'); return false;"', result_id)
|
|
||||||
if cl.is_popup else '',
|
|
||||||
result_repr,
|
|
||||||
table_tag)
|
table_tag)
|
||||||
else:
|
else:
|
||||||
# By default the fields come from ModelAdmin.list_editable, but if we pull
|
# By default the fields come from ModelAdmin.list_editable, but if we pull
|
||||||
|
|
|
@ -630,6 +630,19 @@ class AdminViewBasicTest(AdminViewBasicTestCase):
|
||||||
with self.assertRaises(AttributeError):
|
with self.assertRaises(AttributeError):
|
||||||
self.client.get('/test_admin/%s/admin_views/simple/' % self.urlbit)
|
self.client.get('/test_admin/%s/admin_views/simple/' % self.urlbit)
|
||||||
|
|
||||||
|
def test_changelist_with_no_change_url(self):
|
||||||
|
"""
|
||||||
|
ModelAdmin.changelist_view shouldn't result in a NoReverseMatch if url
|
||||||
|
for change_view is removed from get_urls
|
||||||
|
|
||||||
|
Regression test for #20934
|
||||||
|
"""
|
||||||
|
UnchangeableObject.objects.create()
|
||||||
|
response = self.client.get('/test_admin/admin/admin_views/unchangeableobject/')
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
# Check the format of the shown object -- shouldn't contain a change link
|
||||||
|
self.assertContains(response, '<th class="field-__str__">UnchangeableObject object</th>', html=True)
|
||||||
|
|
||||||
|
|
||||||
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
|
@override_settings(PASSWORD_HASHERS=('django.contrib.auth.hashers.SHA1PasswordHasher',))
|
||||||
class AdminViewFormUrlTest(TestCase):
|
class AdminViewFormUrlTest(TestCase):
|
||||||
|
|
Loading…
Reference in New Issue