Skip to content

Commit

Permalink
[1.7.x] Fixed #23329 -- Allowed inherited and m2m fields to be refere…
Browse files Browse the repository at this point in the history
…nced in the admin.

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

Backport of 3cbb759 from master
  • Loading branch information
charettes committed Aug 28, 2014
1 parent 574f8f5 commit 4883516
Show file tree
Hide file tree
Showing 8 changed files with 79 additions and 5 deletions.
10 changes: 6 additions & 4 deletions django/contrib/admin/options.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -444,11 +444,13 @@ def to_field_allowed(self, request, to_field):
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 in related_object.field.foreign_related_fields): 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
Expand Down
13 changes: 13 additions & 0 deletions docs/releases/1.4.15.txt
Original file line number Original file line Diff line number Diff line change
@@ -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 changes: 13 additions & 0 deletions docs/releases/1.5.10.txt
Original file line number Original file line Diff line number Diff line change
@@ -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>`_)
13 changes: 13 additions & 0 deletions docs/releases/1.6.7.txt
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,13 @@
==========================
Django 1.6.7 release notes
==========================

*Under development*

Django 1.6.7 fixes a regression in the 1.6.6 security release.

Bugfixes
========

* Allowed inherited and m2m fields to be referenced in the admin
:ticket:`23329`
3 changes: 3 additions & 0 deletions docs/releases/index.txt
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ versions of the documentation contain the release notes for any later releases.
.. toctree:: .. toctree::
:maxdepth: 1 :maxdepth: 1


1.6.7
1.6.6 1.6.6
1.6.5 1.6.5
1.6.4 1.6.4
Expand All @@ -45,6 +46,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
Expand All @@ -61,6 +63,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
Expand Down
6 changes: 5 additions & 1 deletion tests/admin_views/admin.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
UnchangeableObject, UserMessenger, Simple, Choice, ShortMessage, Telegram, UnchangeableObject, UserMessenger, Simple, Choice, ShortMessage, Telegram,
FilteredManager, EmptyModelHidden, EmptyModelVisible, EmptyModelMixin, FilteredManager, EmptyModelHidden, EmptyModelVisible, EmptyModelMixin,
State, City, Restaurant, Worker, ParentWithDependentChildren, State, City, Restaurant, Worker, ParentWithDependentChildren,
DependentChild, StumpJoke, FieldOverridePost, FunkyTag) DependentChild, StumpJoke, FieldOverridePost, FunkyTag,
ReferencedByParent, ChildOfReferer, M2MReference)




def callable_year(dt_value): def callable_year(dt_value):
Expand Down Expand Up @@ -881,6 +882,9 @@ class FunkyTagAdmin(admin.ModelAdmin):
site.register(Restaurant, RestaurantAdmin) site.register(Restaurant, RestaurantAdmin)
site.register(Worker, WorkerAdmin) site.register(Worker, WorkerAdmin)
site.register(FunkyTag, FunkyTagAdmin) site.register(FunkyTag, FunkyTagAdmin)
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:
Expand Down
17 changes: 17 additions & 0 deletions tests/admin_views/models.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -822,3 +822,20 @@ class Worker(models.Model):
work_at = models.ForeignKey(Restaurant) work_at = models.ForeignKey(Restaurant)
name = models.CharField(max_length=50) name = models.CharField(max_length=50)
surname = models.CharField(max_length=50) surname = models.CharField(max_length=50)


# 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')
9 changes: 9 additions & 0 deletions tests/admin_views/tests.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -617,6 +617,15 @@ def test_disallowed_to_field(self):
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)

# We also want to prevent the add and change view from leaking a # We also want to prevent the add and change view from leaking a
# disallowed field value. # disallowed field value.
with patch_logger('django.security.DisallowedModelAdminToField', 'error') as calls: with patch_logger('django.security.DisallowedModelAdminToField', 'error') as calls:
Expand Down

0 comments on commit 4883516

Please sign in to comment.