2016-01-13 66 views
1

我認爲可以創建一個自定義敏捷工廠,調用默認工廠,然後將一些子內容(在我的情況下基於原型)添加到創建的「父」敏捷內容。定製Plone靈巧工廠創建子內容

我沒有問題創建和註冊自定義工廠。

但是,無論我使用什麼方法(創建AT子內容),在從自定義工廠內嘗試時,子內容創建都會失敗。

我已經嘗試了所有從plone.api到invokeFactory來直接實例化AT內容類。

在大多數情況下,回溯顯示底層Plone/CMF代碼嘗試使用getToolByName獲取portal_types工具並失敗;類似地,當試圖直接實例化AT類時,manage_afterAdd然後嘗試訪問reference_catalog,其失敗。

有什麼辦法可以使這項工作?

+2

當你說獲取portal_types失敗時,我懷疑你缺少某種收購包裝;這可能是在錯誤的地方做到這一點的一個症狀(例如,IObjectCreatedEvent中新創建的基於敏捷度的文件夾沒有父項並且尚未包裝)。使用IObjectAddedEvent應該可以工作,因爲你應該有一個已經包裝好的對象(參見keul的答案)。 – sdupton

+0

是的,敏捷通過沒有要求或任何種類的情況下工廠,所以沒有收購包裝。 – Petri

回答

6

一種不同的方法可以簡單地爲IObjectAddedEvent添加事件處理程序,並使用公共API添加您的子內容。

+0

是的。或者自定義添加表單。 – Petri

0

一些試驗和錯誤之後,事實證明這是可能的:

from zope.container.interfaces import INameChooser 
from zope.component.hooks import getSite 
from plone.dexterity.factory import DexterityFactory 


class CustomDexterityFactory(DexterityFactory): 

    def __call__(self, *args, **kw): 
     folder = DexterityFactory.__call__(self, *args, **kw) 

     # we are given no context to work with so need to resort to getSite 
     # hook or zope.globalrequest.getRequest and then wrap the folder 
     # in the context of the add view 
     site = getSite() 
     wrapped = folder.__of__(site["PUBLISHED"].context) 

     # invokeFactory fails if the container has no id 
     folder.id = "tmp_folder_id" 

     # standard AT content creation 
     wrapped.invokeFactory("Page", "tmp_obj_id") 
     page = wrapped["tmp_obj_id"] 
     new_id = INameChooser(service_obj).chooseName(title, page) 
     page.setId(new_id) 
     page.setTitle(title) 

     # empty the id, otherwise it will keep 
     folder.id = None 

     return folder 

雖然上述作品,在某些點上創建頁面編入索引(也許invokeFactory),這意味着將有假進入目錄。刪除條目的代碼可以添加到工廠中。

總的來說,只需創建一個事件處理程序就比較容易了,正如@keul在他的回答中所建議的那樣。

+0

是的,事件處理程序是更清潔和可維護的恕我直言。 – gforcada