[ZDP] ZDP's Ad-hoc Zope FAQ version 0.1

Martijn Faassen M.Faassen@vet.uu.nl
Thu, 04 Mar 1999 15:16:50 +0100

Hi everybody,

Here is the new ad-hoc FAQ. I'll start versioning it as of now; this
is version 0.1. How we'll do the actual versioning we'll still have to
decide on, but at least we have a way to refer to this one now.




Note on the use of the Zope mailing lists:

    The Zope Documentation Project is getting its own mailing list
    (zdp@zope.org). In an attempt to gain publicity and support among
    the Zope community, I'll post this development FAQ to the main
    Zope list as well, however. Feel free to respond to it on either
    list for now, but you are encouraged to join the ZDP mailing list
    and to send new FAQ suggestions there.

    You can subscribe to the ZDP mailing list by using the page:


Note on the categorizing of this FAQ:

    This FAQ is a FAQ in progress. It is uncompletely unstructured,
    unrelated questions are mixed haphazardly. If you feel the calling
    to categorize the FAQ or to maintain the questions for a
    particular topic, feel free to mail your changes to the list, and
    thanks in advance!

Note on the code examples and StructuredText:

    I've reconsidered and used normal '<' and '>' characters in sample
    DTML, for the reason that at least the FAQ is readable as text
    then. If you try to feed this FAQ through::
        <!--#var faq.stx fmt="structured-text"-->

    there will be an error message in Zope, however. For some reason
    Zope seems to try to interprete even StructuredText that uses &amp
    escape codes. Until this issue is resolved it is not possible to
    render this document into HTML.

    In my uninformed opinion, StructuredText code examples shouldn't
    be interpreted by Zope as actual DTML. There may be some rather
    subtle technical difficulties involved however. Any input on this
    is very welcome. Until the matter is resolved, the FAQ document
    will use StructuredText in the plaintext readable way.

    Thanks to Martijn Pieters in being so considerate to supply HTML
    escaped DTML examples; it's unfortunate his efforts weren't useful
    this time.

Note on my availability:
    Martijn Faassen (me!), ad-hoc FAQ maintainer of the ZDP's Zope FAQ
    is generally not available to read or respond to email on friday,
    saturday and sunday. It is suggested ZDP related communication
    goes through the ZDP mailing list at zdp@zope.org anyway, and is
    not sent directly Martijn. This way anyone who wants to do
    something for the ZDP (such as editing and extending the FAQ) does
    not have to wait for Martijn to read his mail, having all relevant
    information available on the list.

* How do I return an image from an External Method?

    Example (for a png image)::

        def foo(self, RESPONSE):
            # set the header
            RESPONSE['content-type'] = 'image/png'
            # return the actual image data
            return mkimage()

    Another way to set the header information is::

* How can an External Method refer to the objects in the Zope app?

    Use an External Method that gets passed 'self'. 'self' is your
    hook into Zope world. From 'self' you should be able to get
    anywhere you'd like to go. 

    'self' is the folder in which the external method is
    called. External Methods are methods of Folders. Since External
    Methods are acquired, self is not always the same Folder in which
    the method is defined--it may be a child Folder.

* Is there any way for External Methods to access files on the
  filesystem of the server?

    An External Method can access anything on the server computer that
    the Zope process has access to. Therefore, an External Method can
    do just about anything a Python program can do. This is both a
    power and a liability.
* Can I restrict what an External Method can do? Is there somekind of
  sandbox environment for External Methods?

    Right now there is no sandbox execution environment for External
    Methods. An External Method has access to everything that the Zope
    process has access to. This is one of the reasons why External
    Methods are required to be defined in the Extensions
    directory--it's easier to keep an eye on them there.

* How do I call an external method from DTML?


        <!--#var "external_method_name(arguments)"-->
    to call any External Method in the folder (or acquired by the
    folder). The more explicit alternative is::

        <!--#var expr="external_method_name(arguments)"-->

    The rule is that anything between double quotes in the first
    argument of the #var tag is interpreted as an expression
    attribute; a first argument without quotes is interpreted as a
    name attribute.
* Why does StructuredText have trouble rendering the '#var' tags in
  the FAQ? Why do you use the HTML &amp escape codes in the FAQ when
  they don't work well either?

    I suspect there is some interaction between StructuredText and
    DTML that causes '#var' tags to be interpreted even when in a
    StructuredText code block (indicated by '::' or single quotes). I
    don't know any workaround right now, so I leave in ugly escape
    codes to encourage suggestions. :)

* In a DTML expression, how do I access variable names with a '-' in
  them? (such as 'sequence-item')

    Any variable name (including those with '-') can be accessed in
    the '_' namespace. This contains a dictionary of all variables in
    the default namespace. To access 'sequence-item' you therefore use::


* How do you safely do a backup of the Zope database? ('data.bbb' in
  the 'var' directory)

    In Zope 1.10 and later, you can simply back up the
    data.bbb. Because of the way the file written (all write
    operations are appends), it is highly unlikely for a backup file
    created directly to have a problem. If the database is being
    written while the file is being copied, then the Zope may discard
    the last transaction when reading the copy, if the last record is
    Alternatively, you could export the entire site and backup the
    export file. This won't be a full backup however, as it won't
    contain old revisions of objects.

    Yet another alternative is to (mis)use the Pack operation (in the
    Zope Control Panel, database management). Pack will create a
    Data.bbb.old backup copy of your file before packing (for safety),
    which you could then back up. To exploit this side effect you
    could do a pack that says something ridiculous (like pack anything
    older than thousand days).

* How do I pass a non-form variable to the next requested URL?

    Use Hidden fields within the form::

        <input type="hidden" name="varname" value="<!--#var varname-->">

* How do I define a variable for use in a document

    Set it in REQUEST::

        <!--#call "REQUEST.set('varname', value)"-->

* How do I tell the tree tag to show only Folders?

    By using the objectValues function in the branches_expr attribute
    of the tree tag. The objectValues function of a folder returns all
    objects contained by that folder.

    You can however, specify a list of object metatypes that it should
    return. objectValues(['DTML Document']) will only return all DTML
    Document objects in a Folder. Other metatypes you could select on
    are: Folder, DTML Method, File, Image, Mail Host, User Folder and
    Session.  This is not a complete list, as Products can and will
    define their own metatypes. If you want to show more types, just
    add them to the list, like objValues(['Image', 'File']).
    Example of a Folder tree (with links to them)::

        <!--#tree branches_expr="objectValues(['Folder'])"-->
            <A HREF="<!--#var URL1-->/<!--#var id-->">
            <!--#var title_or_id-->

* How can I collapse or expand a tree using a URL?

    The tree tag will show a tree fully expanded when the 'expand_all'
    variable is present in its namespace. So when a URL, showing a
    tree, is called with ?expand_all=1, the tree tag will expand all
    it's branches.  Collapsing can be achieved with collapse_all.

    The following example shows a tree with collapse and expand

        <A HREF="<!--#var URL0-->?expand_all=1">
          Expand all</A>|
        <A HREF="<!--#var URL0-->?collapse_all=1">
          Collapse all</A>

        <!--#tree--><!--#var id--><!--#/tree-->

* How can I limit a tree to showing only *one* branch at a time?

    Use the 'single' attribute for your tree, like in::

        <!--#tree single--><!--#var id--><!--#/tree-->

* What is the difference between a DTML Method and a DTML Document?

    A DTML Method is what used to be just a Document in pre 1.10
    releases. DTML Methods are not objects, they are methods. If you
    have a folder called 'foo', and it contained a DTML Method called
    'bar', then 'bar' is a method of 'foo'. 'foo' doesn't contain the
    object 'bar', it has the method 'bar' bound to it. What this means
    is that from 'bar''s point of view, 'self' is a Folder object, and
    any properties it sees are properties of 'foo', not itself.

    DTML Documents are Zope Objects. Their idea of 'self' is
    themselves.  They are contained in folders, but are not methods
    bound to that folder, they are instances of
    'DTMLDocument.DTMLDocument'. They can manage their own Properties
    (because they inherit 'PropertyManager.PropertyManager').

    Both DTML Documents and DTML Methods can hold DTML and content.
    The difference is subtle. DTML Methods would be used when the
    answer to the question "Am I showing some other objects content
    through me?" is Yes. DTML Documents should be used when the answer
    to the question "Am I the content I want to display?" is Yes. 

    DTML Methods have the advantage that they don't have any
    properties, and their perspective of aquisition is from their
    containing folders point of view. DTML Documents have properties
    which may interfere with aquisition you'd want to do, and
    aquisition is from their own point of view, which may not be what
    you want.

* How can I show all form data/cookies/REQUEST vars without knowing
their names?

    By using the #in tag, you can easily all show all data in any
    dictionary object, like REQUEST.form, REQUEST.cookies and even
    REQUEST itself. Just call the items() method of the dictionary,
    and the #in tag will provide a sequence-key and sequence-item
    variable for every item in the dictionary.

    Show showing all form data can be done like this::

        <!--#in "REQUEST.form.items()" sort-->
        <!--#var sequence-key-->: <!--#var sequence-item--><BR>

    Use REQUEST.cookies.items() for all your cookies, and
    REQUEST.items() for all REQUEST variables, including CGI
    Environment variables.

* What is a Principia Draft?

    It is a special use of the session object, but it appears to be
    partially broken. When you create a Principia Draft, it asks you
    to specify an orginal object, from the same Folder you are
    creating the Draft in. This will be your 'draft', on which you can
    make changes invisible to the outside world.

    The draft contains an invisible Session object that is immediatly
    started and joined, and an invisible UserFolder to facilitate
    extra users (for example, customers that want to be able to view
    your work on it as well, but have no access to it otherwise).

    The Principia Draft suffers two problems however. The first is
    really a Session object bug, in that security for Session objects
    is broken. The second problem is that the Userfolder and Session
    controls are inaccessible via the management screens.

    The latter problem is caused by convention changes in the Folder
    object (or the ObjectManager class really, used by Folder). I
    think that Folder objects *used* to call 'title_and_id' on a
    object when displaying it in it's management screen, but the
    current release of Zope constructs the id and title of an object
    by using its id and title separately. Principia Drafts made use of
    the call to 'title_and_id' to insert links to its UserFolder and
    Session controls. As this now doesn't happen anymore, you will
    have to do this yourself.

    As long as you have access to Session objects, you can change
    users on a Principia Draft object by calling it's
    'users__draft__.manage_main' method, and reach the Session controls
    by calling its 'manage_approve__draft__' method. The URLS are::