summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/contrib/admin/options.py13
-rw-r--r--tests/admin_views/admin.py2
-rw-r--r--tests/admin_views/tests.py36
3 files changed, 30 insertions, 21 deletions
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py
index e5502c42d5..e05881b16a 100644
--- a/django/contrib/admin/options.py
+++ b/django/contrib/admin/options.py
@@ -2026,13 +2026,16 @@ class ModelAdmin(BaseModelAdmin):
return queryset
return queryset.filter(pk__in=object_pks)
- def _get_formset_with_permissions(self, request, queryset):
+ def _get_formset_with_permissions(self, request, queryset, for_save=False):
"""
Construct a changelist formset, and remove list_editable fields
for objects the user cannot change.
"""
FormSet = self.get_changelist_formset(request)
- formset = FormSet(queryset=queryset)
+ if for_save:
+ formset = FormSet(data=request.POST, files=request.FILES, queryset=queryset)
+ else:
+ formset = FormSet(queryset=queryset)
for form in formset.forms:
if not self.has_change_permission(request, form.instance):
@@ -2158,7 +2161,11 @@ class ModelAdmin(BaseModelAdmin):
modified_objects = self._get_list_editable_queryset(
request, FormSet.get_default_prefix()
)
- cl.formset = FormSet(request.POST, request.FILES, queryset=modified_objects)
+ cl.formset = self._get_formset_with_permissions(
+ request,
+ queryset=modified_objects,
+ for_save=True,
+ )
if cl.formset.is_valid():
self._save_formset(request, cl.formset)
diff --git a/tests/admin_views/admin.py b/tests/admin_views/admin.py
index 5e7a055ec3..d0448a1b64 100644
--- a/tests/admin_views/admin.py
+++ b/tests/admin_views/admin.py
@@ -385,7 +385,7 @@ class PersonNoChangePermissionsAdmin9(admin.ModelAdmin):
def has_change_permission(self, request, obj=None):
if obj is None:
return True
- return obj.id % 2 == 0
+ return obj.alive
class FooAccountAdmin(admin.StackedInline):
diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py
index 1fdb90822c..3dba13d185 100644
--- a/tests/admin_views/tests.py
+++ b/tests/admin_views/tests.py
@@ -5076,14 +5076,14 @@ class AdminViewListEditable(TestCase):
self.client.force_login(self.superuser)
response = self.client.get(reverse("admin9:admin_views_person_changelist"))
- # Editable fields present
- self.assertContains(response, 'name="form-1-gender"')
- self.assertContains(response, 'name="form-1-alive"')
- # Non-editable fields should NOT have inputs
- self.assertNotContains(response, 'name="form-0-gender"')
- self.assertNotContains(response, 'name="form-0-alive"')
- self.assertNotContains(response, 'name="form-2-gender"')
- self.assertNotContains(response, 'name="form-2-alive"')
+ # Non-editable fields should NOT have inputs.
+ self.assertNotContains(response, 'name="form-1-gender"')
+ self.assertNotContains(response, 'name="form-1-alive"')
+ # Editable fields are present.
+ self.assertContains(response, 'name="form-0-gender"')
+ self.assertContains(response, 'name="form-0-alive"')
+ self.assertContains(response, 'name="form-2-gender"')
+ self.assertContains(response, 'name="form-2-alive"')
def test_list_editable_per_object_permissions_submission(self):
"""
@@ -5092,26 +5092,28 @@ class AdminViewListEditable(TestCase):
"""
self.client.logout()
self.client.force_login(self.superuser)
-
+ # Skip the instance lacking edit permission (include only its id).
data = {
"form-TOTAL_FORMS": "3",
"form-INITIAL_FORMS": "3",
"form-MAX_NUM_FORMS": "0",
- "form-0-gender": "2", # Change per1 (not allowed)
+ "form-0-gender": "2",
+ "form-0-alive": "checked",
"form-0-id": str(self.per1.pk),
- "form-1-gender": "2", # Change per2 (allowed)
- "form-1-id": str(self.per2.pk),
- "form-2-gender": "2", # Change per3 (not allowed)
+ "form-1-id": str(self.per2.pk), # not editable
+ "form-2-gender": "2",
+ "form-2-alive": "checked",
"form-2-id": str(self.per3.pk),
"_save": "Save",
}
response = self.client.post(
reverse("admin9:admin_views_person_changelist"), data, follow=True
)
- # per2 and per3 were updated, but per1 was not
- self.assertEqual(Person.objects.get(pk=self.per1.pk).gender, 1) # Unchanged
- self.assertEqual(Person.objects.get(pk=self.per2.pk).gender, 2)
- self.assertEqual(Person.objects.get(pk=self.per3.pk).gender, 1) # Unchanged
+ # per1 and per3 were updated, but per2 was not.
+ self.assertEqual(Person.objects.get(pk=self.per1.pk).gender, 2)
+ self.assertEqual(Person.objects.get(pk=self.per2.pk).gender, 1) # Unchanged
+ self.assertEqual(Person.objects.get(pk=self.per3.pk).gender, 2)
+
# Check for success message
self.assertEqual(len(response.context["messages"]), 1)