2009-12-14 147 views
3

我正在嘗試使用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) 

回答

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

0

我很驚訝是q停留在循環中的同一個對象。

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

+0

感謝您的時間,但這並不能解決問題。我猜lambda中的'q.id'仍然被引用傳遞。 – 2009-12-14 19:57:08

1

正如我在我對安迪利的回答評論中提到的,我剛剛找到了解決方案;使用另一個函數來創建閉包似乎打破了參考,這意味着現在每個動作都指向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())