summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBasil Dubyk <samitnuk.work@gmail.com>2018-11-09 22:41:55 +0200
committerTim Graham <timograham@gmail.com>2018-11-28 15:50:30 -0500
commit381bdd4898bffbe1cbd3020826e6bf4c7cc63254 (patch)
tree7f14f9e137ee27efe85e2c1f7c67c786e5dc1bad
parenta9d9680ea344a243f6e3ed7d0ad8031172458b9a (diff)
[2.1.x] Fixed #29929 -- Fixed admin view-only change form crash when using ModelAdmin.prepopulated_fields.
Backport of 7d1123e5ada60963ba3c708a8932e57342278706 from master.
-rw-r--r--django/contrib/admin/options.py3
-rw-r--r--docs/releases/2.1.4.txt3
-rw-r--r--tests/admin_views/admin.py8
-rw-r--r--tests/admin_views/tests.py19
4 files changed, 32 insertions, 1 deletions
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index 4175eca614..d0948359ab 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -1588,7 +1588,8 @@ class ModelAdmin(BaseModelAdmin):
adminForm = helpers.AdminForm(
form,
list(self.get_fieldsets(request, obj)),
- self.get_prepopulated_fields(request, obj),
+ # Clear prepopulated fields on a view-only form to avoid a crash.
+ self.get_prepopulated_fields(request, obj) if add or self.has_change_permission(request, obj) else {},
readonly_fields,
model_admin=self)
media = self.media + adminForm.media
diff --git a/docs/releases/2.1.4.txt b/docs/releases/2.1.4.txt
index 081b56991d..8ba457846e 100644
--- a/docs/releases/2.1.4.txt
+++ b/docs/releases/2.1.4.txt
@@ -19,3 +19,6 @@ Bugfixes
* Fixed keep-alive support in ``runserver`` after it was disabled to fix
another issue in Django 2.0 (:ticket:`29849`).
+
+* Fixed admin view-only change form crash when using
+ ``ModelAdmin.prepopulated_fields`` (:ticket:`29929`).
diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py
index 04cc6c79e7..5dc2a5811b 100644
--- a/tests/admin_views/admin.py
+++ b/tests/admin_views/admin.py
@@ -459,6 +459,13 @@ class PrePopulatedPostAdmin(admin.ModelAdmin):
return self.prepopulated_fields
+class PrePopulatedPostReadOnlyAdmin(admin.ModelAdmin):
+ prepopulated_fields = {'slug': ('title',)}
+
+ def has_change_permission(self, *args, **kwargs):
+ return False
+
+
class PostAdmin(admin.ModelAdmin):
list_display = ['title', 'public']
readonly_fields = (
@@ -1085,6 +1092,7 @@ site2.register(Person, save_as_continue=False)
site7 = admin.AdminSite(name="admin7")
site7.register(Article, ArticleAdmin2)
site7.register(Section)
+site7.register(PrePopulatedPost, PrePopulatedPostReadOnlyAdmin)
# Used to test ModelAdmin.sortable_by and get_sortable_by().
diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py
index 3930eca929..2d1e58aa26 100644
--- a/tests/admin_views/tests.py
+++ b/tests/admin_views/tests.py
@@ -4218,6 +4218,25 @@ class PrePopulatedTest(TestCase):
response = self.client.get(reverse('admin:admin_views_prepopulatedpostlargeslug_add'))
self.assertContains(response, "&quot;maxLength&quot;: 1000") # instead of 1,000
+ def test_view_only_add_form(self):
+ """
+ PrePopulatedPostReadOnlyAdmin.prepopulated_fields includes 'slug'
+ which is present in the add view, even if the
+ ModelAdmin.has_change_permission() returns False.
+ """
+ response = self.client.get(reverse('admin7:admin_views_prepopulatedpost_add'))
+ self.assertContains(response, 'data-prepopulated-fields=')
+ self.assertContains(response, '&quot;id&quot;: &quot;#id_slug&quot;')
+
+ def test_view_only_change_form(self):
+ """
+ PrePopulatedPostReadOnlyAdmin.prepopulated_fields includes 'slug'. That
+ doesn't break a view-only change view.
+ """
+ response = self.client.get(reverse('admin7:admin_views_prepopulatedpost_change', args=(self.p1.pk,)))
+ self.assertContains(response, 'data-prepopulated-fields="[]"')
+ self.assertContains(response, '<div class="readonly">%s</div>' % self.p1.slug)
+
@override_settings(ROOT_URLCONF='admin_views.urls')
class SeleniumTests(AdminSeleniumTestCase):