[Zope] How to pass values from python script back to calling dtml-method ???

Duncan Booth duncan@rcp.co.uk
Mon, 26 Mar 2001 10:25:32 +0100


> Greeting, people !
Greetings back, but please could you try not to post HTML to the 
mailing list.

> I may seem completely ignorant, but Zope namespaces are driving me
> wild for the last couple of days :-( I need to solve a pretty simple
> task: I have a dtml-method which calls a Python script. When that
> python script is through, it has a variable (say, returnValue="return
> value"). How can I access this variable in calling dtml method ?
> Please help !!!!!
If you want to return a single value, just return it and use dtml-var to 
insert it into your document at one location, or dtml-let to save the 
value for use in several places.
DTML:
    <dtml-var myscript>
PythonScript myscript:
    return "return value"

If you want to return multiple values, then return a namespace 
object and use dtml-with to make the values available for use. The 
example below shows the technique I prefer, which is to make all 
python scripts return a namespace.

For example, the following code is taken from a simple shopping 
basket system. basketSummary displays a one line summary of 
the basket contents:
   <dtml-comment>
   This method returns an HTML segment that displays a summary
   of the contents of the current shopping basket.
   </dtml-comment>
   <dtml-with "logic.basketContents()">
   <p class="small">Shopping Basket: <dtml-var numlines> lines,
   <dtml-var numitems> items, Total Value: <dtml-var totalvalue
        fmt="$%1.2f">
   </p>
   </dtml-with>

The python script basketContents, kept in the logic folder, retrieves 
the current contents of the basket and looks like this:

if not context.REQUEST.has_key('SESSION'):
    context.Session(REQUEST=context.REQUEST)

basket = context.REQUEST.SESSION.get('basket', None) or []
customer = container.customerData()

#  Return the basket contents.
contents = []
totalvalue, items = 0.0, 0
for c, d, u, q, p in basket:
    contents.append(namespace(code=c, description=d, unitprice=u,
        quantity=q, price=p)[0])
    totalvalue, items = totalvalue + p, items + q
shipping = 4.95
total = totalvalue + shipping

vars = namespace(contents=contents, totalvalue=totalvalue,
    shipping=shipping, total=total, numlines=len(contents), numitems=items,
    customer=customer[0])
return vars


Notice that for the summary display we are just interested in the 
totals. The code that does the full display can get at the individual 
lines using dtml-in:
   <dtml-with "logic.basketContents()">
       <dtml-in contents>
            <dtml-var description> <dtml-var unitprice> etc.
      </dtml-in contents>
   </dtml-with>

Note that the namespace function actually returns a tuple 
containing the namespace as the first (only) element. This is fine 
when returning the final result, but for building a list of namespaces 
you have to remove the extra tuple wrapping, hence the [0] in the 
append call (and also the customer[0] since customer was the 
result of another call to namespace).

-- 
Duncan Booth                                             duncan@rcp.co.uk