From: "Brad Clements" <bkc@murkworks.com>
target = traverse_subpath[-1] if target == 'ProductInfo.htm': container.Products(context,productid=traverse_subpath[0])
In this case, you probably want to use: container.Products(container.Products, context.REQUEST, productid=traverse_subpath[0]) ..or.. req = context.REQUEST req.set('productid', traverse_subpath[0]) container.Products(context, req) Lecture time: DTML Methods have the call signature: (client=None, REQUEST={}, RESPONSE=None, **kw) When a Method is the target of a URL, ZPublisher calls it like this: method(context, REQUEST, RESPONSE) The Method creates a namespace and pushes some standard shared data onto it, followed by the REQUEST and the context object (the object on which the method is being called). RESPONSE is just used to set up headers properly, and can be ignored; You shouldn't pass it yourself. Now the context is on top of the namespace, so the Method has access to its attributes (including acquired ones). If a name is not found in the context, the REQUEST is searched next. When DTML calls a DTML Method using <dtml-var method>, it does so like this: method(None, _) The trick, here, is that the namespace "_" already contains the client, request, and keyword arguments that were passed to the *calling* DTML Method. The called Method notices that it has been given a valid namespace, and adopts it. There is no client, and no keyword arguments, so nothing else gets pushed onto the namespace. The called method has access to the exact same set of names as the caller did when it performed the call. When you call a DTML Method from Python, whether it be filesystem code, a Script, or an expression in DTML or a Page Template, you must decide what information to make available to it. If you have access to a properly constructed namespace (it was passed to you, or bound by your Script) you can simply pass it along: method(None, namespace) Otherwise, you will probably want to call it like ZPublisher does, passing a client and the REQUEST. A reasonable client to choose is the object from which you are acquiring the method (assuming that you haven't simply been handed the method), and you can probably acquire the REQUEST from it as well (or from your container). This gives you: container.Products(container.Products, context.REQUEST) If you want to pass additional data, you have two choices. You can use keyword arguments, in which case you might override names in the client or REQUEST. Second, you can add the data to the REQUEST using set(), in which case it might be hidden by names in the client or REQUEST. Cheers, Evan @ digicool & 4-am