Plone tips and tricks
Here is a list of things that I have found useful when developing Plone sites:
- Use ZEO to help you debug
- Verbose Security
- Docfinder bookmarklet
- Find files shell script
- Finding bottlenecks with PTProfiler
Use ZEO to help you debug
Zope Enterprise Objects (ZEO) is normally a way to cluster multiple Zope instances to help performance. However, it can also come in mighty handy for development as it allows you to run the site in debug mode at the same time as having it accessible through the web. To convert your Zope instance to use ZEO, follow these steps:
- Create a ZEO instance:
- Shut down your Zope instance
- Move your Data.fs over to ZEO:
mv /path/to/zope/instance/var/Data.fs <dirname>/var/
- Edit zope.conf:
Edit /path/to/zope/instance/etc/zope.conf Comment out all lines in the first <zodb_db main> section you find Uncomment all lines in the <zodb_db main> section that is given after the words # ZEO client storage:
- Start ZEO:
- Start Zope:
You should now be able to see your Zope install through the web as normal. If all's well, you can also fire up a debug instance:
After a while, you'll see a reassuring >>> prompt. You can now debug your Zope site by typing Python commands (the 'app' object is the top level of your Zope site). If you need to re-sync with the ZODB, type:
Note that any changes you make via the debug prompt are purely temporary. If you need to make these changes permanently (e.g. you've just patched up or deleted some broken objects) then use the following:
To help debug authentication problems, install the VerboseSecurity product (but n.b. to remove it on production sites). Also, to be able to see the errors by preventing redirection to the login page, then temporarily alter the following setting in the ZMI: [portal_root]/cookie_authentication page, set 'Auto-login page ID' to an empty string instead of its default value ('require_login')
Once you have installed the excellent DocFinder Product, then just drag the following bookmarklet to your Firefox/Safari tool bar: DocFinder. Then, once you're viewing a page on your DocFinder-equiped Plone site, all you have to do to see the API of the current object is to click on the bookmarklet.
Find-in-files shell script
A common task is to grep all the Plone source code for a given string. To make this easier, create the following script and call it findinfiles.sh:
#!/bin/bash if [ ! -n "$1" ] then echo "Usage: `basename $0` [expression to find] [optional extension]" exit fi filename="py" if [ -n "$2" ] then filename="$2" fi echo Searching for $1 in *.$filename find . -iname "*.$filename" | xargs grep "$1"
cd to the Products directory of your Zope instance, and run e.g.
findinfiles.sh "def UID" to search *.py files, or e.g.
findinfiles.sh css_slot pt to search in page templates.
Finding bottlenecks with PTProfiler
The best way to profile your site to find slow pages is to install the PTProfiler product in a debug instance of Zope, with the ZPublisher call profiler enabled through use of the publisher-profile-file directive enabled in etc/zope.conf
In the ZMI, at the root level, use the Add Item menu to add a new PTProfiler object.
For each page of the site, load the page in a web browser, then go to the PTProfiler object and clear the results. This ensures that initial ZODB object load overhead is not counted in the performance statistics for page rendering.
Now reload the front-end page in a browser, and examine the results in the PTProfiler. At the top of the list of rendering calls are the TAL expressions that are consuming the most processor time for each page rendering. The most expensive calls are generally those that touch a number of ZODB persistent objects, such as calls to getFolderContents(full_objects=True).
Refactor your templates to avoid the most expensive calls, and re-test. Voila - speedy site.
If you get these, create a user.js file in ~/Library/Application Support/Firefox/Profiles/xxxxxxx.default that contains the following lines:
user_pref("capability.policy.policynames", "allowclipboard"); user_pref("capability.policy.allowclipboard.sites", "http://cms.icons.org.uk"); user_pref("capability.policy.allowclipboard.Clipboard.cutcopy", "allAccess"); user_pref("capability.policy.allowclipboard.Clipboard.paste", "allAccess");