Fixed #23329 -- Allowed inherited and m2m fields to be referenced in the admin.

Thanks to Trac alias Markush2010 and ross for the detailed reports.

Backport of 3cbb759 from master
This commit is contained in:
Simon Charette 2014-08-21 11:55:23 -04:00
parent 5d647e5f17
commit 4c96bd8fb3
7 changed files with 65 additions and 5 deletions

View File

@ -284,11 +284,13 @@ class BaseModelAdmin(six.with_metaclass(forms.MediaDefiningClass)):
return False return False
# Make sure at least one of the models registered for this site # Make sure at least one of the models registered for this site
# references this field. # references this field through a FK or a M2M relationship.
registered_models = self.admin_site._registry registered_models = self.admin_site._registry
for related_object in opts.get_all_related_objects(): for related_object in (opts.get_all_related_objects() +
if (related_object.model in registered_models and opts.get_all_related_many_to_many_objects()):
field == related_object.field.rel.get_related_field()): related_model = related_object.model
if (any(issubclass(model, related_model) for model in registered_models) and
related_object.field.rel.get_related_field() == field):
return True return True
return False return False

13
docs/releases/1.4.15.txt Normal file
View File

@ -0,0 +1,13 @@
===========================
Django 1.4.15 release notes
===========================
*Under development*
Django 1.4.15 fixes a regression in the 1.4.14 security release.
Bugfixes
========
* Allowed inherited and m2m fields to be referenced in the admin
(`#22486 <http://code.djangoproject.com/ticket/23329>`_)

13
docs/releases/1.5.10.txt Normal file
View File

@ -0,0 +1,13 @@
===========================
Django 1.5.10 release notes
===========================
*Under development*
Django 1.5.10 fixes a regression in the 1.5.9 security release.
Bugfixes
========
* Allowed inherited and m2m fields to be referenced in the admin
(`#22486 <http://code.djangoproject.com/ticket/23329>`_)

View File

@ -25,6 +25,7 @@ versions of the documentation contain the release notes for any later releases.
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
1.5.10
1.5.9 1.5.9
1.5.8 1.5.8
1.5.7 1.5.7
@ -41,6 +42,7 @@ versions of the documentation contain the release notes for any later releases.
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1
1.4.15
1.4.14 1.4.14
1.4.13 1.4.13
1.4.12 1.4.12

View File

@ -28,7 +28,7 @@ from .models import (Article, Chapter, Account, Media, Child, Parent, Picture,
AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod, AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod,
AdminOrderedCallable, Report, Color2, UnorderedObject, MainPrepopulated, AdminOrderedCallable, Report, Color2, UnorderedObject, MainPrepopulated,
RelatedPrepopulated, UndeletableObject, UserMessenger, Simple, Choice, RelatedPrepopulated, UndeletableObject, UserMessenger, Simple, Choice,
ShortMessage, Telegram) ShortMessage, Telegram, ReferencedByParent, ChildOfReferer, M2MReference)
def callable_year(dt_value): def callable_year(dt_value):
@ -703,6 +703,9 @@ site.register(Report, ReportAdmin)
site.register(MainPrepopulated, MainPrepopulatedAdmin) site.register(MainPrepopulated, MainPrepopulatedAdmin)
site.register(UnorderedObject, UnorderedObjectAdmin) site.register(UnorderedObject, UnorderedObjectAdmin)
site.register(UndeletableObject, UndeletableObjectAdmin) site.register(UndeletableObject, UndeletableObjectAdmin)
site.register(ReferencedByParent)
site.register(ChildOfReferer)
site.register(M2MReference)
# We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2. # We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2.
# That way we cover all four cases: # That way we cover all four cases:

View File

@ -678,3 +678,21 @@ class Simple(models.Model):
class Choice(models.Model): class Choice(models.Model):
choice = models.IntegerField(blank=True, null=True, choice = models.IntegerField(blank=True, null=True,
choices=((1, 'Yes'), (0, 'No'), (None, 'No opinion'))) choices=((1, 'Yes'), (0, 'No'), (None, 'No opinion')))
# Models for #23329
class ReferencedByParent(models.Model):
pass
class ParentWithFK(models.Model):
fk = models.ForeignKey(ReferencedByParent)
class ChildOfReferer(ParentWithFK):
pass
class M2MReference(models.Model):
ref = models.ManyToManyField('self')

View File

@ -571,6 +571,15 @@ class AdminViewBasicTest(TestCase):
response = self.client.get("/test_admin/admin/admin_views/section/", {TO_FIELD_VAR: 'id'}) response = self.client.get("/test_admin/admin/admin_views/section/", {TO_FIELD_VAR: 'id'})
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
# Specifying a field referenced by another model though a m2m should be allowed.
response = self.client.get("/test_admin/admin/admin_views/m2mreference/", {TO_FIELD_VAR: 'id'})
self.assertEqual(response.status_code, 200)
# Specifying a field that is not refered by any other model directly registered
# to this admin site but registered through inheritance should be allowed.
response = self.client.get("/test_admin/admin/admin_views/referencedbyparent/", {TO_FIELD_VAR: 'id'})
self.assertEqual(response.status_code, 200)
def test_allowed_filtering_15103(self): def test_allowed_filtering_15103(self):
""" """
Regressions test for ticket 15103 - filtering on fields defined in a Regressions test for ticket 15103 - filtering on fields defined in a