我正在尝试使用ModelAdmin
上的get_actions()
方法动态构建管理操作列表。每个操作都与另一个模型的特定实例相关,并且可以添加或删除新实例,我想确保操作列表反映出这一点。
这是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))
(元组返回值的奇怪重复字典由Django docs for get_actions()
解释。)
正如预期的那样,这会产生一个适当命名的管理操作列表,用于批量分配Quality
个Package
个对象的外键。
问题是我选择的任何操作,相同的Quality
对象都会分配给选定的Package
。
我假设我使用lambda
关键字创建的闭包都包含对同一q
对象的引用,因此每次迭代都会为每次更改q
的值功能
我是否可以破坏此引用,允许我仍然使用包含q
的不同值的闭包列表?
编辑:我意识到在此示例中不需要lambda
。而不是:
action = lambda modeladmin, req, qset: qset.update(quality=q)
我可以简单地使用def
:
def action(modeladmin, req, qset):
return qset.update(quality=q)
答案 0 :(得分:5)
尝试
def make_action(quality):
return lambda modeladmin, req, qset: qset.update(quality=quality)
for q in models.Quality.objects.all():
action = make_action(q)
name = "mark_%s" % (q,)
yield (name, (action, name, "Mark selected as %s quality" % (q,)))
如果这不起作用,我怀疑该错误与您使用yield
有关。也许试试:
def make_action(quality):
name = 'mark_%s' % quality
action = lambda modeladmin, req, qset: qset.update(quality=quality)
return (name, (action, name, "Mark selected as %s quality" % quality))
def get_actions(self, request):
return dict([make_action for q in models.Quality.objects.all()])
答案 1 :(得分:1)
正如我在对andylei的回答中提到的那样,我刚刚找到了解决方案;使用另一个函数来创建闭包似乎打破了引用,这意味着现在每个动作都引用了Quality
的正确实例。
def create_action(quality):
fun = lambda modeladmin, request, queryset: queryset.update(quality=quality)
name = "mark_%s" % (quality,)
return (name, (fun, name, "Mark selected as %s quality" % (quality,)))
class PackageAdmin(admin.ModelAdmin):
list_display = ('name', 'quality')
def get_actions(self, request):
return dict(create_action(q) for q in models.Quality.objects.all())
答案 2 :(得分:0)
我很惊讶q在循环中保持相同的对象。
它适用于你的lambda中的quality=q.id
吗?