Code

Opened 3 years ago

Closed 3 years ago

#17380 closed Uncategorized (wontfix)

Default value of ModelAdmin.inlines can be altered.

Reported by: schinckel Owned by: nobody
Component: contrib.admin Version: 1.3
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Because ModelAdmin.inlines is defined as an empty list, if you have not altered this in a ModelAdmin subclass, and then add to it, you actually add that inline to every ModelAdmin subclass that does not override inlines.

class MyModelAdmin(admin.ModelAdmin):

pass

if 'other_app' in settings.INSTALLED_APPS:

MyModelAdmin.inlines += [OtherInline]

This bug rears its head if you try to add two (or more) inlines to UserAdmin.

I do have what seems like a fix: in ModelAdmin.init(), we can do:

self.inlines = self.inlines or []

This will set self.inlines to a new empty list if the original value was falsy.

Attachments (0)

Change History (2)

comment:1 follow-up: Changed 3 years ago by charettes

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

Your fix won't work:

class A(object):
  inlines = []
  
  def __init__(self):
    self.inlines = self.inlines or []
    
class B(A):
  pass
  
B.inlines += [1]

b = B()

print b.inlines #[1]
print B.inlines #[1]
print A.inlines #[1]

If you want to achieve this behavior you should re-define inlines as an empty list when subclassing ModelAdmin:

class A(object):
  inlines = []
    
class B(A):
  inlines = []
  
B.inlines += [1]

b = B()

print b.inlines #[1]
print B.inlines #[1]
print A.inlines #[]

I would say it's the expected behavior.

comment:2 in reply to: ↑ 1 Changed 3 years ago by carljm

  • Resolution set to wontfix
  • Status changed from new to closed

I would say it's the expected behavior.

I agree. Mutating mutable objects mutates them. Class attributes that aren't overridden by a subclass are still the superclass attribute. This is just how Python works; I can't see what other behavior would be expected, or what reasonable code would "fix" this. It would have to be a class property, I think, which is quite unusual and just not worth it.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.