diff options
| author | Artyom Kotovskiy <artyomkotovskiy@gmail.com> | 2026-04-10 00:27:14 -0400 |
|---|---|---|
| committer | Jacob Walls <jacobtylerwalls@gmail.com> | 2026-04-22 10:13:58 -0400 |
| commit | 84db026228413dda4cd195464554d51c0b208e32 (patch) | |
| tree | 9d5602570a2f242a76e06c97a8bc0215a00920eb /django | |
| parent | 512e348bb271878a1e4f1ab6ae187a22dd16222b (diff) | |
Fixed #15759 -- Excluded fields by per-object permissions for ModelAdmin.list_editable.
Instead of going over all objects in a queryset and filtering
by user permissions, added skipping while saving the formset
so there is no need to refetch objects again.
Diffstat (limited to 'django')
| -rw-r--r-- | django/contrib/admin/options.py | 20 |
1 files changed, 18 insertions, 2 deletions
diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 2d37f26de1..bb091e4c52 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -2022,10 +2022,27 @@ class ModelAdmin(BaseModelAdmin): return queryset return queryset.filter(pk__in=object_pks) + def _get_formset_with_permissions(self, request, queryset): + """ + 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) + + for form in formset.forms: + if not self.has_change_permission(request, form.instance): + for field_name in self.list_editable: + form.fields.pop(field_name, None) + + return formset + def _save_formset(self, request, formset): changecount = 0 with transaction.atomic(using=router.db_for_write(self.model)): for form in formset.forms: + if not self.has_change_permission(request, form.instance): + continue if form.has_changed(): obj = self.save_form(request, form, change=True) if obj._state.adding: @@ -2145,8 +2162,7 @@ class ModelAdmin(BaseModelAdmin): # Handle GET -- construct a formset for display. elif cl.list_editable and self.has_change_permission(request): - FormSet = self.get_changelist_formset(request) - cl.formset = FormSet(queryset=cl.result_list) + cl.formset = self._get_formset_with_permissions(request, cl.result_list) # Build the list of media to be used by the formset. if cl.formset: |
