1
0
mirror of https://github.com/django/django.git synced 2025-06-05 11:39:13 +00:00

[2.1.x] Fixed #29723 -- Fixed crash if InlineModelAdmin.has_add_permission() doesn't accept the obj argument.

* Refs #27991 -- Added testing for ModelAdmin.get_inline_instances() if the inline's has_add_permission() doesn't accept 'obj'.

* Fixed #29723 -- Fixed crash if InlineModelAdmin.has_add_permission() doesn't accept the obj argument.

Backport of fd8a7a5313f5e223212085b2e470e43c0047e066 from master
This commit is contained in:
Tim Graham 2018-08-30 05:22:50 -04:00 committed by Carlton Gibson
parent e7acd99113
commit 152b1d783b
3 changed files with 57 additions and 8 deletions

View File

@ -584,13 +584,8 @@ class ModelAdmin(BaseModelAdmin):
inline_instances = [] inline_instances = []
for inline_class in self.inlines: for inline_class in self.inlines:
inline = inline_class(self.model, self.admin_site) inline = inline_class(self.model, self.admin_site)
# RemovedInDjango30Warning: obj will be a required argument.
args = get_func_args(inline.has_add_permission)
if 'obj' in args:
inline_has_add_permission = inline.has_add_permission(request, obj)
else:
inline_has_add_permission = inline.has_add_permission(request)
if request: if request:
inline_has_add_permission = inline._has_add_permission(request, obj)
if not (inline.has_view_or_change_permission(request, obj) or if not (inline.has_view_or_change_permission(request, obj) or
inline_has_add_permission or inline_has_add_permission or
inline.has_delete_permission(request, obj)): inline.has_delete_permission(request, obj)):
@ -1483,7 +1478,7 @@ class ModelAdmin(BaseModelAdmin):
for inline, formset in zip(inline_instances, formsets): for inline, formset in zip(inline_instances, formsets):
fieldsets = list(inline.get_fieldsets(request, obj)) fieldsets = list(inline.get_fieldsets(request, obj))
readonly = list(inline.get_readonly_fields(request, obj)) readonly = list(inline.get_readonly_fields(request, obj))
has_add_permission = inline.has_add_permission(request, obj) has_add_permission = inline._has_add_permission(request, obj)
has_change_permission = inline.has_change_permission(request, obj) has_change_permission = inline.has_change_permission(request, obj)
has_delete_permission = inline.has_delete_permission(request, obj) has_delete_permission = inline.has_delete_permission(request, obj)
has_view_permission = inline.has_view_permission(request, obj) has_view_permission = inline.has_view_permission(request, obj)
@ -2001,6 +1996,11 @@ class InlineModelAdmin(BaseModelAdmin):
js.append('collapse%s.js' % extra) js.append('collapse%s.js' % extra)
return forms.Media(js=['admin/js/%s' % url for url in js]) return forms.Media(js=['admin/js/%s' % url for url in js])
def _has_add_permission(self, request, obj):
# RemovedInDjango30Warning: obj will be a required argument.
args = get_func_args(self.has_add_permission)
return self.has_add_permission(request, obj) if 'obj' in args else self.has_add_permission(request)
def get_extra(self, request, obj=None, **kwargs): def get_extra(self, request, obj=None, **kwargs):
"""Hook for customizing the number of extra inline forms.""" """Hook for customizing the number of extra inline forms."""
return self.extra return self.extra
@ -2046,7 +2046,7 @@ class InlineModelAdmin(BaseModelAdmin):
base_model_form = defaults['form'] base_model_form = defaults['form']
can_change = self.has_change_permission(request, obj) if request else True can_change = self.has_change_permission(request, obj) if request else True
can_add = self.has_add_permission(request, obj) if request else True can_add = self._has_add_permission(request, obj) if request else True
class DeleteProtectedModelForm(base_model_form): class DeleteProtectedModelForm(base_model_form):

View File

@ -46,3 +46,6 @@ Bugfixes
``values_list()`` after combining querysets with ``extra()`` with ``values_list()`` after combining querysets with ``extra()`` with
``union()``, ``difference()``, or ``intersection()`` crashed due to ``union()``, ``difference()``, or ``intersection()`` crashed due to
mismatching columns (:ticket:`29694`). mismatching columns (:ticket:`29694`).
* Fixed crash if ``InlineModelAdmin.has_add_permission()`` doesn't accept the
``obj`` argument (:ticket:`29723`).

View File

@ -1,4 +1,8 @@
from datetime import date
from django.contrib.admin.options import ModelAdmin, TabularInline from django.contrib.admin.options import ModelAdmin, TabularInline
from django.contrib.admin.sites import AdminSite
from django.test import TestCase
from django.utils.deprecation import RemovedInDjango30Warning from django.utils.deprecation import RemovedInDjango30Warning
from .models import Band, Song from .models import Band, Song
@ -56,3 +60,45 @@ class HasAddPermissionObjTests(CheckTestCase):
) )
with self.assertWarnsMessage(RemovedInDjango30Warning, msg): with self.assertWarnsMessage(RemovedInDjango30Warning, msg):
self.assertIsValid(BandAdmin, Band) self.assertIsValid(BandAdmin, Band)
class MockRequest:
method = 'POST'
FILES = {}
POST = {}
class SongInline(TabularInline):
model = Song
def has_add_permission(self, request):
return True
class BandAdmin(ModelAdmin):
inlines = [SongInline]
class ModelAdminTests(TestCase):
def setUp(self):
self.band = Band.objects.create(name='The Doors', bio='', sign_date=date(1965, 1, 1))
self.song = Song.objects.create(name='test', band=self.band)
self.site = AdminSite()
self.request = MockRequest()
self.request.user = self.MockAddUser()
self.ma = BandAdmin(Band, self.site)
class MockAddUser:
def has_perm(self, perm):
return perm == 'modeladmin.add_band'
def test_get_inline_instances(self):
self.assertEqual(len(self.ma.get_inline_instances(self.request)), 1)
def test_get_inline_formsets(self):
formsets, inline_instances = self.ma._create_formsets(self.request, self.band, change=True)
self.assertEqual(len(self.ma.get_inline_formsets(self.request, formsets, inline_instances)), 1)
def test_get_formsets_with_inlines(self):
self.assertEqual(len(list(self.ma. get_formsets_with_inlines(self.request, self.band))), 1)