[Zope-CMF] adding a type with a new factory method
Karl Anderson
kra@monkey.org
22 Jul 2002 11:29:08 -0700
Florent Guillaume <fg@nuxeo.com> writes:
> Karl Anderson <kra@monkey.org> wrote:
> > I'm trying to create a new type based on an existing one (CMFPost,
> > part of CMFForum).
> >
> > Right now, I'm only trying to change the factory method. So, I copied
> > the CMFPost type to MyCMFPost, and changed the factory method to
> > "myAddPost". To create myAddPost, I added an External Method to the
> > portal root, adapted from CMFPost.addPost, the old factory method (in
> > the Python product).
> >
> > However, this fails, apparently because the External Method is called
> > differently - self isn't the container. I couldn't use a
> > Script(Python), because I can't call _setObject from it.
> >
> > I finally got this working (so far) by adding a keyword argument called
> > 'thecontainer' to the External Method, and having the skin that the
> > MyCMFPost-adding action uses pass its context as the 'thecontainer'
> > argument to context.invokeFactory (I couldn't use 'container', because
> > PortalTypes.constructContent() complained about extra values for that
> > keyword argument, which I still don't understand).
> Usually my factory method are in the product, not in external methods,
> so I don't know what's your problem exactly. Could you post your
> problematic code?
I copied the portal type "Post" to "PostCS", and changed the factory
method from "addPost" to "addPostCS".
addPostCS is an External Method in the portal root. addPost was a
function imported from Post.py (confusingly, a method of the Post
class, also referenced in the module scope and exported there -
possibly because posts can be added to forums and to other posts). I
needed to us an External Method becuase it had to call _setObject.
This external method is what's making me think that I should stop
trying to follow CMF's aspect philosophy and subclass Post :)
I customized the skin post_add to invoke the factory for PostCS.
This is what is called by the relevant UI skin to add a post.
post_add:
## Script (Python) "post_add"
##bind container=container
##bind context=context
##bind namespace=_
##bind script=script
##bind subpath=traverse_subpath
##parameters=author='', email='', text='', title='', submit='', file=''
##title=Add a new Post
##
member = context.portal_membership.getAuthenticatedMember()
new_id='msg_' + str(int( context.ZopeTime()))
context.invokeFactory('PostCS', id=new_id, title=title,
email=member.getProperty('email'),
author=member.getId(), text=text, file=file,
thecontainer=context)
url = '%s/%s' % (context.absolute_url(), context.getTypeInfo().getActionById('view',''))
return context.REQUEST.RESPONSE.redirect(url)
addPostCS.py:
def addPostCS(id='', title='', text='', author='', email='', file=None,
REQUEST=None, **kw):
"""Add a Post to its container"""
from Products.CMFForum.Post import Post, generate_id
# we can't pass a kw of 'container' for some reason
thecontainer = kw['thecontainer']
if not id:
id = generate_id(thecontainer)
item = Post(id, title=title, text=text, author=author, email=email)
thecontainer._setObject(id, item)
post = getattr(thecontainer, id)
if file and file.filename:
id = string.split(file.filename, "\\")[-1]
body = file.read()
content_type = file.headers['Content-Type']
if guess_content_type(id, body)[0][0:5] == 'image':
post.invokeFactory( 'Image', id=id, file=file, content_type=content_type)
else:
post.invokeFactory( 'File', id=id, file=file, content_type=content_type)
#if REQUEST is not None:
# return .manage_main(self, REQUEST)
--
Karl Anderson kra@monkey.org http://www.monkey.org/~kra/