Author: julien
Date: 2011-08-28 00:57:56 -0700 (Sun, 28 Aug 2011)
New Revision: 16705
Modified:
django/trunk/django/contrib/admin/views/main.py
django/trunk/tests/regressiontests/admin_filters/tests.py
django/trunk/tests/regressiontests/admin_views/tests.py
Log:
Fixed #16716 -- Fixed two small regressions in the development version
introduced in r16144 where the changelist crashed with a 500 error instead of
nicely operating a 302 redirection back to the changelist.
The two specific cases were:
* a lookup through a non-existing field and apparently spanning multiple
relationships (e.g. "?nonexistant__whatever=xxxx").
* a proper list_filter's queryset failing with an exception. In Django 1.3 the
queryset was only directly manipulated by the changelist, whereas in 1.4 the
list_filters may manipulate the queryset themselves. The fix here implies
catching potential failures from the list_filters too.
Modified: django/trunk/django/contrib/admin/views/main.py
===================================================================
--- django/trunk/django/contrib/admin/views/main.py 2011-08-28 06:49:29 UTC
(rev 16704)
+++ django/trunk/django/contrib/admin/views/main.py 2011-08-28 07:57:56 UTC
(rev 16705)
@@ -267,6 +267,7 @@
del lookup_params[key]
lookup_params[smart_str(key)] = value
+ field = None
if not use_distinct:
# Check if it's a relationship that might return more than one
# instance
@@ -291,7 +292,7 @@
value = True
lookup_params[key] = value
- if not self.model_admin.lookup_allowed(key, value):
+ if field and not self.model_admin.lookup_allowed(key, value):
raise SuspiciousOperation("Filtering by %s not allowed" % key)
return lookup_params, use_distinct
@@ -300,28 +301,30 @@
lookup_params, use_distinct =
self.get_lookup_params(use_distinct=False)
self.filter_specs, self.has_filters = self.get_filters(request,
use_distinct)
- # Let every list filter modify the qs and params to its liking
- qs = self.root_query_set
- for filter_spec in self.filter_specs:
- new_qs = filter_spec.queryset(request, qs)
- if new_qs is not None:
- qs = new_qs
- for param in filter_spec.used_params():
- try:
- del lookup_params[param]
- except KeyError:
- pass
+ try:
+ # First, let every list filter modify the qs and params to its
+ # liking.
+ qs = self.root_query_set
+ for filter_spec in self.filter_specs:
+ new_qs = filter_spec.queryset(request, qs)
+ if new_qs is not None:
+ qs = new_qs
+ for param in filter_spec.used_params():
+ try:
+ del lookup_params[param]
+ except KeyError:
+ pass
- # Apply the remaining lookup parameters from the query string (i.e.
- # those that haven't already been processed by the filters).
- try:
+ # Then, apply the remaining lookup parameters from the query string
+ # (i.e. those that haven't already been processed by the filters).
qs = qs.filter(**lookup_params)
- # Naked except! Because we don't have any other way of validating
"params".
- # They might be invalid if the keyword arguments are incorrect, or if
the
- # values are not in the correct type, so we might get FieldError,
ValueError,
- # ValicationError, or ? from a custom field that raises yet something
else
- # when handed impossible data.
except Exception, e:
+ # Naked except! Because we don't have any other way of validating
+ # "lookup_params". They might be invalid if the keyword arguments
+ # are incorrect, or if the values are not in the correct type, so
+ # we might get FieldError, ValueError, ValicationError, or ? from a
+ # custom field that raises yet something else when handed
+ # impossible data.
raise IncorrectLookupParameters(e)
# Use select_related() if one of the list_display options is a field
Modified: django/trunk/tests/regressiontests/admin_filters/tests.py
===================================================================
--- django/trunk/tests/regressiontests/admin_filters/tests.py 2011-08-28
06:49:29 UTC (rev 16704)
+++ django/trunk/tests/regressiontests/admin_filters/tests.py 2011-08-28
07:57:56 UTC (rev 16705)
@@ -1,9 +1,9 @@
import datetime
+from django.contrib.admin.options import IncorrectLookupParameters
from django.core.exceptions import ImproperlyConfigured
from django.test import TestCase, RequestFactory
from django.utils.encoding import force_unicode
-
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import User
from django.contrib.admin.views.main import ChangeList
@@ -50,6 +50,11 @@
def lookups(self, request, model_admin):
pass
+class
DecadeListFilterWithFailingQueryset(DecadeListFilterWithTitleAndParameter):
+
+ def queryset(self, request, queryset):
+ raise Exception
+
class
DecadeListFilterWithQuerysetBasedLookups(DecadeListFilterWithTitleAndParameter):
def lookups(self, request, model_admin):
@@ -84,6 +89,9 @@
class DecadeFilterBookAdminWithNoneReturningLookups(ModelAdmin):
list_filter = (DecadeListFilterWithNoneReturningLookups,)
+class DecadeFilterBookAdminWithFailingQueryset(ModelAdmin):
+ list_filter = (DecadeListFilterWithFailingQueryset,)
+
class DecadeFilterBookAdminWithQuerysetBasedLookups(ModelAdmin):
list_filter = (DecadeListFilterWithQuerysetBasedLookups,)
@@ -509,6 +517,17 @@
filterspec = changelist.get_filters(request)[0]
self.assertEqual(len(filterspec), 0)
+ def test_filter_with_failing_queryset(self):
+ """
+ Ensure that a filter's failing queryset is interpreted as if incorrect
+ lookup parameters were passed (therefore causing a 302 redirection to
+ the changelist).
+ Refs #16716, #16714.
+ """
+ modeladmin = DecadeFilterBookAdminWithFailingQueryset(Book, site)
+ request = self.request_factory.get('/', {})
+ self.assertRaises(IncorrectLookupParameters, self.get_changelist,
request, Book, modeladmin)
+
def test_simplelistfilter_with_queryset_based_lookups(self):
modeladmin = DecadeFilterBookAdminWithQuerysetBasedLookups(Book, site)
request = self.request_factory.get('/', {})
Modified: django/trunk/tests/regressiontests/admin_views/tests.py
===================================================================
--- django/trunk/tests/regressiontests/admin_views/tests.py 2011-08-28
06:49:29 UTC (rev 16704)
+++ django/trunk/tests/regressiontests/admin_views/tests.py 2011-08-28
07:57:56 UTC (rev 16705)
@@ -410,6 +410,11 @@
"""Ensure incorrect lookup parameters are handled gracefully."""
response = self.client.get('/test_admin/%s/admin_views/thing/' %
self.urlbit, {'notarealfield': '5'})
self.assertRedirects(response, '/test_admin/%s/admin_views/thing/?e=1'
% self.urlbit)
+
+ # Spanning relationships through an inexistant related object (Refs
#16716)
+ response = self.client.get('/test_admin/%s/admin_views/thing/' %
self.urlbit, {'notarealfield__whatever': '5'})
+ self.assertRedirects(response, '/test_admin/%s/admin_views/thing/?e=1'
% self.urlbit)
+
response = self.client.get('/test_admin/%s/admin_views/thing/' %
self.urlbit, {'color__id__exact': 'StringNotInteger!'})
self.assertRedirects(response, '/test_admin/%s/admin_views/thing/?e=1'
% self.urlbit)
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en.