Index: docs/ref/contrib/admin/index.txt
===================================================================
--- docs/ref/contrib/admin/index.txt	(revisión: 16345)
+++ docs/ref/contrib/admin/index.txt	(copia de trabajo)
@@ -949,6 +949,14 @@
                     instance.save()
                 formset.save_m2m()
 
+.. attribute:: ModelAdmin.get_changelist(self)
+
+    .. versionadded:: 1.2
+
+    Returns the Changelist class to be used for listing. By default,
+    ``django.contrib.admin.views.main.ChangeList`` is used. By inheriting this
+    class you can change the behavior of the listing.
+
 .. method:: ModelAdmin.get_readonly_fields(self, request, obj=None)
 
     .. versionadded:: 1.2
@@ -1892,3 +1900,38 @@
 
 For more details, see the documentation on :ref:`reversing namespaced URLs
 <topics-http-reversing-url-namespaces>`.
+
+Security considerations
+=======================
+
+The Django administrative interface, django.contrib.admin, supports filtering
+of displayed lists of objects by fields on the corresponding models, including
+across database-level relationships. This is implemented by passing lookup
+arguments in the querystring portion of the URL. This means URLs like these::
+
+    /admin/persons/person/?name=Juan
+
+This could be used maliciously to obtain private information through URLs like
+these::
+
+    /admin/persons/person/?salary__gt=30000
+
+To avoid the information leakage in Django administrative interface, only are
+allowed URLs which match with fields explicitly defined in filters or searching
+options.
+
+But you could need to allow some other GET parameters to include it in your
+custom admin logic. For example if you wants an extra ``hidecolumns`` parameter
+to hide the columns in a list, you have to allow this param explicitly by
+overriding the ``ChangeList.get_ignored_lookup_params()`` method as follows::
+
+    class HidingColumnsChangeList(ChangeList):
+
+        def get_ignored_lookup_params(self):
+            return super(HidingColumnsChangeList, self).get_ignored_lookup_params() + \
+                ('hidecolumns', )
+
+    class PersonAdmin(ModelAdmin):
+
+        def get_changelist(self):
+            return HidingColumnsChangeList
Index: tests/regressiontests/admin_views/tests.py
===================================================================
--- tests/regressiontests/admin_views/tests.py	(revisión: 16345)
+++ tests/regressiontests/admin_views/tests.py	(copia de trabajo)
@@ -507,6 +507,8 @@
         try:
             self.client.get("/test_admin/admin/admin_views/thing/?color__value__startswith=red")
             self.client.get("/test_admin/admin/admin_views/thing/?color__value=red")
+            # allowed explicitly in a custom changelist
+            self.client.get("/test_admin/admin/admin_views/album/?allowed_param=1")
         except SuspiciousOperation:
             self.fail("Filters are allowed if explicitly included in list_filter")
 
Index: tests/regressiontests/admin_views/models.py
===================================================================
--- tests/regressiontests/admin_views/models.py	(revisión: 16345)
+++ tests/regressiontests/admin_views/models.py	(copia de trabajo)
@@ -620,6 +620,11 @@
     def get_query_set(self, request):
         return self.root_query_set.filter(pk=9999) # Does not exist
 
+class AllowedParamChangeList(ChangeList):
+
+    def get_ignored_lookup_params(self):
+        return super(AllowedParamChangeList, self).get_ignored_lookup_params() + ('allowed_param', )
+
 class GadgetAdmin(admin.ModelAdmin):
     def get_changelist(self, request, **kwargs):
         return CustomChangeList
@@ -706,6 +711,9 @@
 class AlbumAdmin(admin.ModelAdmin):
     list_filter = ['title']
 
+    def get_changelist(self, request, **kwargs):
+        return AllowedParamChangeList
+
 class Employee(Person):
     code = models.CharField(max_length=20)
 
Index: django/contrib/admin/views/main.py
===================================================================
--- django/contrib/admin/views/main.py	(revisión: 16345)
+++ django/contrib/admin/views/main.py	(copia de trabajo)
@@ -252,10 +252,13 @@
                 ordering_fields[idx] = 'desc' if pfx == '-' else 'asc'
         return ordering_fields
 
+    def get_ignored_lookup_params(self):
+        return IGNORED_PARAMS
+
     def get_lookup_params(self, use_distinct=False):
         lookup_params = self.params.copy() # a dictionary of the query string
 
-        for ignored in IGNORED_PARAMS:
+        for ignored in self.get_ignored_lookup_params():
             if ignored in lookup_params:
                 del lookup_params[ignored]
 
