Ben*_*mes 3 python django closures
我正在尝试使用a上的get_actions()方法动态构建管理操作列表ModelAdmin.每个操作都与另一个模型的特定实例相关,并且可以添加或删除新实例,我想确保操作列表反映出这一点.
这是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))
Run Code Online (Sandbox Code Playgroud)
(Django docsget_actions()解释了元组返回值的奇怪重复dict .)
正如所料,这会产生一个适当命名的管理操作列表,用于批量分配对象的Quality外键Package.
问题是无论我选择哪个动作,都会将相同的Quality对象分配给选定的Packages.
我认为我与创建关闭lambda关键字都含有相同的参考q对象,所以每次迭代改变的价值q为每一个功能.
我可以打破这个引用,允许我仍然使用包含不同值的闭包列表q吗?
编辑:我意识到lambda在这个例子中没有必要.代替:
action = lambda modeladmin, req, qset: qset.update(quality=q)
Run Code Online (Sandbox Code Playgroud)
我可以简单地使用def:
def action(modeladmin, req, qset):
return qset.update(quality=q)
Run Code Online (Sandbox Code Playgroud)
尝试
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,)))
Run Code Online (Sandbox Code Playgroud)
如果这不起作用,我怀疑这个bug与你的使用有关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()])
Run Code Online (Sandbox Code Playgroud)
正如我在对 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())
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2431 次 |
| 最近记录: |