I am trying to dynamically build a list of admin actions using the get_actions()
method on a ModelAdmin
. Each action relates to a particular instance of another model, and as new instances may be added or removed, I want to make sure the list of actions reflects that.
Here's the ModelAdmin
:
class PackageAdmin(admin.ModelAdmin):
list_display = ('name', 'quality')
def _actions(self, request):
for q in models.Quality.objects.all():
action = lambda modeladmin, req, qset: qset.update(quality=q)
name = "mark_%s" % (q,)
yield (name, (action, name, "Mark selected as %s quality" % (q,)))
def get_actions(self, request):
return dict(action for action in self._actions(request))
(The weird repetitive dict of tuples return value is explained by the Django docs for get_actions()
.)
As expected, this results in a list of appropriately named admin actions for bulk assignment of Quality
foreign keys to Package
objects.
The problem is that whichever action I choose, the same Quality
object gets assigned to the selected Package
s.
I assume that the closures I am creating with the lambda
keyword all contain a reference to the same q
object, so every iteration changes the value of q
for every function.
Can I break this reference, allowing me to still use a list of closures containing different values of q
?
Edit: I realise that lambda
is not necessary in this example. Instead of:
action = lambda modeladmin, req, qset: qset.update(quality=q)
I could simply use def
:
def action(modeladmin, req, qset):
return qset.update(quality=q)