[Zope-CMF] dynamic list of content-types for the zope ZMI

Tres Seaver tseaver@zope.com
Tue, 08 Jan 2002 05:41:52 -0500


Oliver Bleutgen wrote:

> Tres Seaver wrote:
> 
>> Oliver Bleutgen wrote:
>>
>>> Hi,
>>>
>>> I'm trying to find my way through the API for CMF filesystem products.
>>> Bjorn Stabell pointed out to me how to use portal_types + 
>>> portal_skins to get a fixed product with changeable "templates".
>>>
>>> What I want to do is to write a product which can be added through 
>>> the ZMI (not the CMF GUI) and where the user can select which template
>>> it will use (through selecting the portal_type).
>>>
>>> The problem is now that I can't know beforehand which different 
>>> portal_types will be based on an object of that meta_type, and I'd 
>>> like to dynamically gather that list at the moment the user wants to 
>>> add an instance.
>>>
>>> AFAIK, CMF-products use CMFCore.utils.manage_addContentForm(), which 
>>> knows about the content_types lastly from utils.ContentInit(...),
>>> done in the products __init__.py, where content_types = 
>>> (tuple_of_objects,) is passed.
>>>
>>> Is there a way to stay within the framework (i.e. still use 
>>> utils.manage_addContentForm) and get the addForm to show the 
>>> content_types dynamically? Using ComputedAttribute perhaps?
>>
>>
>>
>>
>> Have a look at how the 'folder_factories' skin method does it
>>
>> (basically, it acquires the 'portal_types' tool and then queries
>> it for type information objects).
>>
>> Tres.
> 
> 
> Tres,
> thanks for your answer, but I suspect I didn't quite explain myself
>  the right way.
> For the normal ZMI, CMF-products seem to use utils.manage_addContentForm 
> as the addForm - consistently.
> This method gathers the right meta_types and passes them
> to addInstance form which finally renders the addForm.
> 
>     tl = []
>     for t in ci.content_types:
>         tl.append(t.meta_type)
>     return addInstanceForm(addInstanceForm, self, REQUEST,
>                            factory_action='manage_addContent',
>                            factory_meta_type=ci.meta_type,
>                            factory_icon=None,
>                            factory_types_list=tl,
>                            factory_need_id=1)
> 
> Perhaps my question is more of a python question.
> Can I achieve ci.content_types to be dynamic? Perhaps with usage of 
> ComputedAttribute in my products __init__.py?
> As I understand it, your answer covers the things to do after I know how 
> to do what I'm not able to ATM.

You are not going to be able to reuse 'manage_addContentForm'
(which is, in fact, half-broken), if that is what you want.
The issue here is that CMF content needs to know explicitly
about its "portal_type", as well as its "meta_type";  unless
you end up calling 'invokeFactory', passing 'type_name' (or do
the equivalent work yourself), that binding won't be set up.

To do what you want, you need to query the types tool for a list
of type names (filtered by metatype, I guess) and use that list
to build your ZMI-based add form::

   # Generate list of type names based on 'Foo' metatype.
   type_objs = getToolByName( self, 'portal_types' )
   my_types = filter( lambda x: x.Metatype() == 'Foo', type_objs )
   type_names = map( lambda x: x.Type(), my_types )

You can then use 'type_names' to build your add form.

Tres.
-- 
===============================================================
Tres Seaver                                tseaver@zope.com
Zope Corporation      "Zope Dealers"       http://www.zope.com