Django管理员应用程序:构建动态管理员动作列表

Django管理员应用程序:构建动态管理员动作列表

问题描述:

我正在尝试使用ModelAdmin上的get_actions()方法动态构建管理员动作列表。每个动作都与另一个模型的特定实例相关,并且随着新实例的添加或删除,我想确保动作列表反映了这一点。Django管理员应用程序:构建动态管理员动作列表

这里的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 s。

我认为我与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) 

尝试

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()]) 
+0

谢谢,我刚刚找到类似于您的第二个建议的解决方案,并且在阅读本文时即将发布。为你的时间+1。 – 2009-12-14 19:58:27

+0

我正在努力争取这项工作。你能为此发布完整的工作示例吗? – 2010-02-09 21:08:42

+0

啊。可疑: (编辑 - 无评论格式的代码!无赖...) 'def get_actions(self,request): def make_action(quality): name ='mark_%s'%quality action = lambda modeladmin,req,qset:qset.update(quality = quality) return(name ,(动作,名称,“马克被选为%s质量”%质量)) return dict(在model.Quality.objects.all中使用make_action(q)) ' – 2010-02-09 21:17:25

我很惊讶是q停留在循环中的同一个对象。

它是否与你的lambda中的quality=q.id一起工作?

+0

感谢您的时间,但这并不能解决问题。我猜lambda中的'q.id'仍然被引用传递。 – 2009-12-14 19:57:08

正如我在我对安迪利的回答评论中提到的,我刚刚找到了解决方案;使用另一个函数来创建闭包似乎打破了参考,这意味着现在每个动作都指向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())