summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/contrib/admin/options.py9
-rw-r--r--docs/releases/1.4.17.txt9
-rw-r--r--tests/regressiontests/admin_views/admin.py5
-rw-r--r--tests/regressiontests/admin_views/models.py24
-rw-r--r--tests/regressiontests/admin_views/tests.py16
5 files changed, 42 insertions, 21 deletions
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 12291605ee..a4bfd8821e 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -281,9 +281,9 @@ class BaseModelAdmin(object):
except FieldDoesNotExist:
return False
- # Check whether this model is the origin of a M2M relationship
- # in which case to_field has to be the pk on this model.
- if opts.many_to_many and field.primary_key:
+ # Always allow referencing the primary key since it's already possible
+ # to get this information from the change view URL.
+ if field.primary_key:
return True
# Make sure at least one of the models registered for this site
@@ -294,8 +294,7 @@ class BaseModelAdmin(object):
for inline in admin.inlines:
registered_models.add(inline.model)
- for related_object in (opts.get_all_related_objects(include_hidden=True) +
- opts.get_all_related_many_to_many_objects()):
+ for related_object in opts.get_all_related_objects(include_hidden=True):
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):
diff --git a/docs/releases/1.4.17.txt b/docs/releases/1.4.17.txt
index f8785bcea2..6279941733 100644
--- a/docs/releases/1.4.17.txt
+++ b/docs/releases/1.4.17.txt
@@ -4,7 +4,14 @@ Django 1.4.17 release notes
*Under development*
-Django 1.4.17 ...
+Django 1.4.17 fixes a regression in the 1.4.14 security release.
Additionally, Django's vendored version of six, :mod:`django.utils.six`, has
been upgraded to the latest release (1.8.0).
+
+Bugfixes
+========
+
+* Fixed a regression with dynamically generated inlines and allowed field
+ references in the admin
+ (`#23754 <http://code.djangoproject.com/ticket/23754>`_).
diff --git a/tests/regressiontests/admin_views/admin.py b/tests/regressiontests/admin_views/admin.py
index d6c26ac535..a35d556348 100644
--- a/tests/regressiontests/admin_views/admin.py
+++ b/tests/regressiontests/admin_views/admin.py
@@ -28,7 +28,7 @@ from .models import (Article, Chapter, Account, Media, Child, Parent, Picture,
AdminOrderedField, AdminOrderedModelMethod, AdminOrderedAdminMethod,
AdminOrderedCallable, Report, Color2, UnorderedObject, MainPrepopulated,
RelatedPrepopulated, ReferencedByParent, ChildOfReferer, M2MReference,
- ReferencedByInline, InlineReference, InlineReferer, Ingredient)
+ ReferencedByInline, InlineReference, InlineReferer, Recipe, Ingredient, NotReferenced)
def callable_year(dt_value):
@@ -627,7 +627,6 @@ site.register(MainPrepopulated, MainPrepopulatedAdmin)
site.register(UnorderedObject, UnorderedObjectAdmin)
site.register(ReferencedByParent)
site.register(ChildOfReferer)
-site.register(M2MReference)
site.register(ReferencedByInline)
site.register(InlineReferer, InlineRefererAdmin)
@@ -656,7 +655,9 @@ site.register(AdminOrderedModelMethod, AdminOrderedModelMethodAdmin)
site.register(AdminOrderedAdminMethod, AdminOrderedAdminMethodAdmin)
site.register(AdminOrderedCallable, AdminOrderedCallableAdmin)
site.register(Color2, CustomTemplateFilterColorAdmin)
+site.register(Recipe)
site.register(Ingredient)
+site.register(NotReferenced)
# Register core models we need in our tests
from django.contrib.auth.models import User, Group
diff --git a/tests/regressiontests/admin_views/models.py b/tests/regressiontests/admin_views/models.py
index 5546a09e64..ff70c9f9d9 100644
--- a/tests/regressiontests/admin_views/models.py
+++ b/tests/regressiontests/admin_views/models.py
@@ -611,11 +611,13 @@ class UnorderedObject(models.Model):
# Models for #23329
class ReferencedByParent(models.Model):
- pass
+ name = models.CharField(max_length=20, unique=True)
class ParentWithFK(models.Model):
- fk = models.ForeignKey(ReferencedByParent)
+ fk = models.ForeignKey(
+ ReferencedByParent, to_field='name', related_name='hidden+',
+ )
class ChildOfReferer(ParentWithFK):
@@ -625,13 +627,16 @@ class ChildOfReferer(ParentWithFK):
class M2MReference(models.Model):
ref = models.ManyToManyField('self')
+
# Models for #23431
class ReferencedByInline(models.Model):
- pass
+ name = models.CharField(max_length=20, unique=True)
class InlineReference(models.Model):
- fk = models.ForeignKey(ReferencedByInline, related_name='hidden+')
+ fk = models.ForeignKey(
+ ReferencedByInline, to_field='name', related_name='hidden+',
+ )
class InlineReferer(models.Model):
@@ -640,9 +645,14 @@ class InlineReferer(models.Model):
# Models for #23604
class Recipe(models.Model):
- name = models.CharField(max_length=20)
+ pass
class Ingredient(models.Model):
- name = models.CharField(max_length=20)
- recipes = models.ManyToManyField('Recipe', related_name='ingredients')
+ recipes = models.ManyToManyField(Recipe)
+
+
+# Model for #23839
+class NotReferenced(models.Model):
+ # Don't point any FK at this model.
+ pass
diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
index 4a972d215d..4c699b477f 100644
--- a/tests/regressiontests/admin_views/tests.py
+++ b/tests/regressiontests/admin_views/tests.py
@@ -582,26 +582,30 @@ class AdminViewBasicTest(TestCase):
with self.assertRaises(DisallowedModelAdminToField):
response = self.client.get("/test_admin/admin/admin_views/section/", {TO_FIELD_VAR: 'name'})
- # Specifying a field referenced by another model should be allowed.
- response = self.client.get("/test_admin/admin/admin_views/section/", {TO_FIELD_VAR: 'id'})
+ # #23839 - Primary key should always be allowed, even if the referenced model isn't registered.
+ response = self.client.get("/test_admin/admin/admin_views/notreferenced/", {TO_FIELD_VAR: 'id'})
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'})
+ # XXX: We're not testing against a non-primary key field since the admin doesn't
+ # support it yet, ref #23862
+ response = self.client.get("/test_admin/admin/admin_views/recipe/", {TO_FIELD_VAR: 'id'})
self.assertEqual(response.status_code, 200)
- # #23604 - Specifying the pk of this model should be allowed when this model defines a m2m relationship
+ # #23604 - Specifying a field referenced through a reverse m2m relationship should be allowed.
+ # XXX: We're not testing against a non-primary key field since the admin doesn't
+ # support it yet, ref #23862
response = self.client.get("/test_admin/admin/admin_views/ingredient/", {TO_FIELD_VAR: 'id'})
self.assertEqual(response.status_code, 200)
# #23329 - 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'})
+ response = self.client.get("/test_admin/admin/admin_views/referencedbyparent/", {TO_FIELD_VAR: 'name'})
self.assertEqual(response.status_code, 200)
# #23431 - Specifying a field that is only refered to by a inline of a registered
# model should be allowed.
- response = self.client.get("/test_admin/admin/admin_views/referencedbyinline/", {TO_FIELD_VAR: 'id'})
+ response = self.client.get("/test_admin/admin/admin_views/referencedbyinline/", {TO_FIELD_VAR: 'name'})
self.assertEqual(response.status_code, 200)
def test_allowed_filtering_15103(self):