[Zope] 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.
Regards,
Martijn
----
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:
http://www.zope.org/mailman/listinfo/zdp
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 &
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::
RESPONSE.setHeader('content-type','image/png')
* 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?
Use::
<!--#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 & 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::
_['sequence-item']
* 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
incomplete.
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-->
</A>
<!--#/tree-->
* 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
'buttons'::
<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>
<!--#/in-->
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::
http://yoursever.com/Zope/Draft/users__draft__/manage_main
and::
http://yoursever.com/Zope/Draft/manage_approve__draft__