Personal tools
You are here: Home Weblog Plone

Plone


2010-02-24

Generating products outside of the Products.* namespace with ArchGenXML

Filed Under:

I'm a die hard in regards to ArchGenXML usage. The number of things to know about when creating new content types for Plone is just too high. Package structure, Zope package registration, content types registration, QuickInstaller registration, GenericSetup profiles, skins registration, workflows, etc. I can go in and do changes to the code, and add to it, but generating it from scratch is a gigantic task, especially for my use case, where I need to start a new project with about 7 content types.

Now to the problem: ArchGenXML assumes (and hardcodes in its templates) the Products.* prefix for your package. I don't have any problems with it, but my employer uses a different package structure so for uniformity I need to follow their standards. 15 minutes of poking and changing through agx enabled me to change it so it would generate GS xml files with the proper namespace (based on a new model level TGV named "namespace" that I have created). After assessing the difficulty of the task and being under time pressure, I've decided to go the dumb route, which I'm documenting below:

My generation script is something like this:

./archgenxml -c archgenxml.cfg myproduct.zuml 

#rename Products.myproduct to ns.myproduct
find myproduct/* -type f -print | xargs sed -i 's/Products\.myproduct/ns\.myproduct/g'

#in the xml type profiles, replace myproduct by ns.myproduct
find myproduct/* -type f -print | xargs sed -i 's/>myproduct</>ns\.myproduct</g'

#in the profiles.zcml, rename the profile to ns.myproduct
find myproduct/* -type f -print | xargs sed -i 's/title=\"myproduct\"/title=\"ns\.myproduct\"/g'

Notice the sed lines, which change the source code to point to "ns.myproduct" instead of "Products.myproduct". Now there's just two more problems, which are actually AGX bugs:

  • the FilesystemDirectoryViews registered for the skin are incorect, so you'll need to insert this in ns/myproduct/__init__.py
from Products.CMFCore import utils
from Globals import package_home
from os.path import dirname
ppath = utils.ProductsPath
utils.ProductsPath.append(dirname(package_home(product_globals)))
DirectoryView.registerDirectory('skins', product_globals)
utils.ProductsPath = ppath
  • trying to get AGX to output the code inside a two level deep folder doesn't work (it crashes), so you'll need to move this script file and the model just above the "myproduct" folder, inside the "ns" namespace.

That's about it. Hopefully I'll find the time to fix the two bugs and add the namespace improvement in the next week. Still need to do the review for Plone for Education, which I have received for free from the publisher.

2009-04-16

The sorry state of internationalization in Plone

Filed Under:

Ever since Plone 2.5 stopped being the hot new thing in the Plone world, the state of content internationalization support in Plone has been declining. Partly due to the difficulty of extending Zope 2 products, LinguaPlone has always been a hack, but at least back then it worked. These days I'm not heavily involved with Plone, but whenever I need to add LinguaPlone to a Plone 3 site, I cringe and weep, especially that those projects never allocate time for me to fix the obvious problems. Some of those problems, in current Plone 3.3 rc2 are:

  • the flags are no longer grayed to indicate that a certain translation is unavailable
  • the switchLanguage script doesn't work anymore, it won't redirect you to the translated content; the LanguageTool is broken (won't take VHM into consideration) and an update was released, but the versions.cfg file on plone.org hasn't been updated yet, so you need to add a [versions] section, with the correct specification for the Products.PloneLanguageTool
  • the changeLanguage script was removed, in favor of doing a direct translation. Wops, now it's possible to translate into neutral, which gets you fast into an ugly traceback that you won't be able to get rid of.
  • the language neutral behaviour for fields is broken. Example: I have a content type with the neutral fields, when translating a content item the content of those fields is erased. This is something that I'll have to fix.

On the upside, the translation management mechanism (after some hickups) has improved.

I don't have access to the Plone subversion. I already had some discussions with two of the developers that have done the latest changes to LP, but they either didn't understand the problems or didn't have time to do the fixes themselves. To make it easier for myself and stimulate my interest in the LP development, I have copied the latest LP trunk to Collective, in a location called Products.LinguaPlone-Unofficial. This version also has a check for the case when there's a translation into Neutral, so it should fix the error detailed above.

Update:

Another problems solved: I've wanted to be able to switch languages based on the subdomain (ro.site.com, en.site.com), which should be supported by the PloneLanguageTool, but didn't work for me. Digging down, I found the problem: plone.i18n.locales.cctld has a list that associates TLDs to languages, but most of the TLDs don't have a language associated to them! This issue should be at least highlighted in the documentation for PloneLanguageTool.

One more weird problem, which caused me to blame LP for even more problems than it has at fault: upgrading as site from Plone 3.2 to 3.3 rc2 broke the LP language selector, by making the default Plone one override the LP one (where it should be the other way). I was able to solve the problem by customizing the template for the LP language selector (with no change)

2009-02-15

Using mechanize to process protected Plone pages

Filed Under:

One of my long-running projects involves a workflow where content is produced in a Plone site, with the data later extracted and processed in various ways (including scripting Scribus to layout this data in a book). Initially the site where the content was produced wasn't protected, so I could run a simple urllib script to download the content and process it using lxml. A recent change in the workflow security settings meant this script didn't work anymore and I had to remember how to login into a Plone site using urllib2. Some google searches found me nothing, but I remembered that the zope.testbrowser can be easily used to run a programatical browsing session, complete with cookies support. But trying to install zope.testbrowser standalone in a buildout didn't lend to too much success, due to some dependency problems (and even after I covered for those dependencies, it still broke somewhere in zope.app.testing).

The solution was to use just the mechanize package, on top of which zope.testbrowser is built. mechanize has a slightly different API (more modern) and doesn't do so much handholding as zope.testbrowser, but I only need to process one form. In the end my script looks something like this (the asxmllist page is just an xml page that returns a list of urls to the entities that I want to process):

import lxml.etree
import os
import os.path
import urllib
import mechanize

loginurl = "http://example.com/login_form"
listurl = "http://example.com/asxmllist"

def run():
    curdir = os.getcwd()
    datadir = os.path.join(curdir, 'data')
    if not os.path.exists(datadir):
        os.makedirs(datadir)
    
    b = mechanize.Browser()
    b.open(loginurl)
    b.select_form(nr=1)
    b['__ac_name'] = "username"
    b['__ac_password'] = "password"
    b.submit()
    b.open(listurl)
    etree = lxml.etree.parse(b.response())
    
    for entry in etree.xpath('//entry'):
        url = entry.get('url')
        print "Processing " + url
        e = lxml.etree.parse(b.open(url + '/asxml'))
        id = e.find('id').text
        print "Got entry " + id
        fpath = os.path.join(datadir, id + '.xml')
        f = open(fpath, 'w')
        xml = lxml.etree.tostring(e)
        f.write(xml)
        f.close()
        print "Saved " + fpath

if __name__ == "__main__":
    run()

2009-02-11

Variable keys in dictionaries with Page Templates TALES syntax

Filed Under:

I admit, I didn't knew this until now. In the following construction:

<div tal:content="somedict/keyname/someattr" />

"keyname" is taken as a string, it's the literal name of the key for the somedict mapping. To use a variable instead of the literal value of the key name, I used to do:

<div tal:content="python somedict[key].someattr" />

Browsing through the zope.app.catalog code, I saw that there's actually a way to use the TALES syntax:

<div tal:content="somedict/?key/someattr" />

I'm not sure that this works with TTW code in Zope 2 (I expect that it works with browser views), so I'll just have to try this next time I have the chance.

2009-01-06

A list of Javascript files loaded by Plone 2.5

Filed Under:

A simple deployment of a Plone 2.5 site (I know, antiquated) means that the pages shown for anonymous users are loaded with JS and CSS content that they will not need. They are, usually, the biggest group of visitors, so it is important do make the pages load fast, to have a good impression for first time visitors. The introduction of the Resource Registry in Plone 2.5 makes it easy to set the order and the conditions to load each resource (and, as a result, the merging conditions between resource files), but there's no page to document what each JS file does, for example (AFAIK). Because of my recent need to optimize such a site, I've created a list of the javascript files loaded by Plone 2.5. Plone 3.x makes it even easier to make sure that you get the minimum number of merged resource files by having the "Automatic grouping" function, but for Plone 2.5 I had to rearange the files myself to get the best result (3 JS files: one for anonymous users, one for users that are authenticated and one that is loaded for Kupu).

Crossroads: a very good load balancing solution

Filed Under:

Recently Martin Aspeli published a very nice buildout recipe that implements a complete setup for a production Zope/Plone server. One of the key components in that setup is the load balancer, which is implemented using the load balancer capabilities of nginx. Nginx might be a good load balancer, but it has a problem with the way Zope/Plone works: the first page loads, for a newly restarted Plone instance are very slow (especially if the site or the catalogs are big). It would be nice to have a way of telling nginx to take out one of the Zope instances from the cluster and then add it back once it's restarted and has its caches warmed. Sure, you could probably script something that would change the buildout options and reload nginx, but why bother when there's a load balancer that offers this and much more?

Crossroads (in its second version, at the moment 2.41) might lack the popularity when compared to perlball, pound or haproxy and may not even have the same features or performances (it's good enough for my needs and I haven't cross-benchmarked), but it's fast, easy to configure and, best of all, it can be configured to provide a web configuration/administration interface. This way, when a Zope server needs to be updated, I can take out the ZEO client from the balancer, restart it in supervisor, warm up the caches by calling the zope sites directly and then add it back to the cluster. The only faults that I could find to it is that the compilation mechanism is not very well tested (I couldn't complete an install with a specific destination prefix. Just checkout the Crossroads trunk or a tag and do a "make local", then you can use the xr binary from that folder). On the other hand, it's pretty well featured: it has sticky sessions, HTTP awarness (although its documentation recommends treating the http servers with the TCP algorithm), can use an external program to determine backend states (and could be plugged this way with Zope's ICP support), etc.

Below is a screenshot of the Crossroads administration interface, with Crossroads started with the following script:

#!/bin/sh

XR=/usr/sbin/xr
SERVER="-s http:127.0.0.1:7000"
BACKENDS="-b 127.0.0.1:9080 -b 127.0.0.1:9081"
ALGORITHM="-dl"
HTTP_FLAGS="-x -X"
TIMEOUTS="-t 10"
CHECK_CALLS="-c 10"
WEB_INTERFACE="-W 127.0.0.1:7020"
#DEBUGGING="-v"
DEBUGGING=""

$XR $SERVER $BACKENDS $ALGORITHM $HTTP_FLAGS $TIMEOUTS $CHECK_CALLS $WEB_INTERFACE $DEBUGGING

Crossroads administration interface

2008-11-18

Subversion 1.5 + default instalation Plone 3.1 buildout: no problems here

Filed Under:

I've hit the setuptools + subversion 1.5 problem again with a freshly install Plone 3.1.7 buildout: I've added my egg develop folder in zinstance/src/, I've added the egg in the relevant sections in buildout.cfg, but it wouldn't work because of the incompatibility with the old setuptools version.

The solution is to upgrade the installed setuptools to the latest version. For example, for a standalone Plone installed at /home/tibi/Plone, we have this structure:

/home/tibi/Plone
   /Python-2.4
   /buildout-cache
   /zinstance

I've changed directory to the Python-2.4 from above and ran:

bin/easy_install -U setuptools

Then I could succesfully run the buildout in the zinstance folder.

2008-07-11

Hosting Plone and Zope 3 applications using nginx

Filed Under:

I'm doing a setup on a new server, I've decided to replace the default Apache 2.2 with an nginx http server. The setup which is needed for Zope 3 and Plone applications is the following:

[buildout]
parts =
    nginx
    nginxctl

[nginx]
recipe = gocept.cmmi
url = http://sysoev.ru/nginx/nginx-0.7.6.tar.gz
md5sum = ae7ce6f66a2cf5a5970d9a9a0da0cf7d

[nginxctl]
recipe = gocept.nginx
hostname = localhost
port = 80
configuration =
    worker_processes 1;
    events {
        worker_connections 1024;
    }
    http {
            upstream z3 {
                server 127.0.0.1:8080;
            }
            upstream plone {
                server 127.0.0.1:9080;
            }
        server {
            listen      ${nginxctl:port};
            server_name z3.example.org;
            root html;
            include /etc/nginx/proxy.conf

            location / {
                proxy_pass http://z3/++lang++ro/++skin++myskin/mysite/++vh++http:z3.example.org:80/++/;
            }
        }
        server {
            server_name plone.example.org;
            include /etc/nginx/proxy.conf

            location / {
                proxy_pass http://plone/VirtualHostBase/http/plone.example.org:80/t1/VirtualHostRoot/;
            }
        }
        server {
            server_name plone.example.org;
            rewrite ^/(.*)  /VirtualHostBase/http/plone.example.org:80/t1/VirtualHostRoot/$1 last;
            location / {
                proxy_pass http://plone;
            }
        }
    }

Note: this is a buildout.cfg. Using it together with zc.buildout makes the nginx instalation a very simple process: install zc.buildout (easy_install zc.buildout), and then run buildout in the folder that contains the .cfg file.

The settings in proxy.conf are important. Without a valid proxy_temp_path, for some reason delivery of all content that came from a Plone 2.5 site that used CacheFu setup with no proxy cache was freezing at 16014 bytes. The paths in /var/nginx need to be created and set to be writable by the nginx process (user nobody in my case).

client_max_body_size            0;
client_body_buffer_size    128k;
client_body_temp_path      /var/nginx/client_body_temp;

proxy_connect_timeout      90;
proxy_send_timeout         90;
proxy_read_timeout         90;
proxy_buffer_size          4k;
proxy_buffers              4 32k;
proxy_busy_buffers_size    64k;
proxy_temp_file_write_size 64k;
proxy_temp_path            /var/nginx/proxy_temp;
proxy_redirect                  off;
proxy_set_header                Host $host;
proxy_set_header                X-Real-IP $remote_addr;
proxy_set_header                X-Forwarded-For $proxy_add_x_forwarded_for;

 

Resources

A more complete nginx sample configuration file (but that only covers how to configure Plone)

Grok guide on hosting Zope 3 with nginx (note, at this moment the document is wrong, the setup line is missing a slash at the end).

2008-04-15

In case you're having problems installing ssl-for-setuptools...

Filed Under:

I've stumbled on this error when trying to install a easyshop buildout:

Exception: No SSL support found
An error occured when trying to install ssl-for-setuptools 1.10.Look above this message for any errors thatwere output by easy_install.
While:
  Installing instance.
  Getting distribution for 'ssl-for-setuptools'.
Error: Couldn't install: ssl-for-setuptools 1.10

After scratching my head for a while, I've found the solution:

# apt-get install libssl-dev

2008-04-08

A tip on debugging Zope 2 with ZEO

Filed Under:

I'm having some troubles with CacheFu, and I've resorted to deleting some objects from a debug prompt, which is very easy to get at if one runs the Zope under ZEO. Still, I couldn't delete the objects because I was getting Unauthorized errors. Luckily, there is #plone, from which I got the following tip:

<naro> from AccessControl.SecurityManagement import newSecurityManager
<naro> user = app.acl_users.getUser('admin')
<naro> newSecurityManager(None, user)

Thanks, naro! 

Update: I realize now that I didn't write how to connect to ZEO:

#bin/instance debug

or

#bin/zopectl debug

This will connect the ZEO client and drop you in a python shell

2008-03-18

A few ATReferenceBrowserWidget tips

Filed Under:

On a Plone 2.5 project I'm working I have a content type that has 3 reference association to another content type. ArchGenXML generated the fields with the same name, which means that in the interface there will be just one field, as they overwrite each other. To have them working I need to rename them, but how to do this from the model? Agx, at first glance, doesn't have support for this. While playing and even trying to change agx to support this use case, I've noticed that agx considers the "association end" as the one meaningful: all tagged values set to it are reflected in the generated case. So the solution to this problem is to set a "name" tagged value in the "end" of the direct associations relationships. Check the following screenshot from Poseidon to see what I mean:

 

Field name in association

 

Another issue, this time directly related to the ATReferenceBrowserIssue, is the startup directory support. The widget has support for defaults set in portal_properties/site_properties, a property called refwidget_startupdirectories. The wording of this property's description in the README left me, as a non-native English speaker, a bit clueless. After some digging and debugging, I found out that the format for the lines there is:

/pathA:/pathB

where pathA is a path relative to the Plone site root; when you call the reference browser widget for an object in this path, the second path, pathB is returned as a base for browsing for objects. Even after I have understood the thing about the two colon separated path, it didn't work for me because I was refering to paths with their absolute paths (based in the Zope root) instead of their paths relative to the Plone site.

 

2008-03-17

GHOP Plone skins overview

Filed Under:

Plone has very few skins available from the community, when compared to just about anything. The skin incompatibilities that appeared between Plone versions 2.0/2.1/3.0 further deepen this problem. As a result of the 2007 Plone - GHOP there are some skins placed in the collective, but they're not visible anywhere (they're not published in the PSC, only some of them are available as eggs in PyPI, to get a glimpse of them you need to install them). These skins are placed under the plonetheme namespace, along with other skins, unrelated to GHOP.

To make them a bit more visible (and to serve as a personal reminder for their design), I'm showcasing them here. In reviewing them I've used Plone 3.1 (the trunk of the ploneout package).  After each skin was installed and snapshotted, I've uninstalled it and installed the next one.

Click on each thumbnail to get to the full image.

Andreas 01

Andreas01 - anonymous view  Andreas01 - editor view

One of the nicer skin, it stands out through its center align design, different sized columns and its simplicity. I can see myself using this skin as a base for a skin customization.

BlueBlog


BlueBlog - anonymous  BlueBlog - editor

This skin, as its name implies, is better suited for a blog, through its tall, thin design. Not a programmers blog though, and that's too bad, as it's a good skin.

Essay


Essay - anonymous  Essay - editor

Nice skin, I especially like the portlet design. Somewhat simple, though. If I'd customize this skin, I'd make it wider (maybe make it whole page instead of center-centred)

Green Community


GreenCommunity - anonymous  GreenCommunity - editor

A non-conformist skin, but still good looking. From what I have seen watching the PyPI, it's still under active development. There are some problems with it, though: the login portlet at the top is not fully visible, the "editor" version is missing some bits of the full skin. Still, it could be used for blog-ish type of sites, after some customizations.

Grok

Grok - anonymous  Grok - editor

This skin is very similar (might be the same) to the one used for the Grok project website. Probably not a GHOP skin. Although it seems like a very simple customization of default Plone, there are many issues with it that would mean that it would require heavy work to make it publishable for a real website.

Napoli

This is an almost empty skin, no point in showing it here

Pizza


Pizza - anonymous  Pizza - editor

Not a GHOP skin, this skin was created in a sprint. I believe its aim is to be one of the official supported skin. It is somewhat similar to NuPlone. Still needs work, though.

Plone2Kiss

Another empty skin

Python

Python - anonymous  Python - editor

Very similar to the current python.org skin. It feels rough and unfinished, but otherwise a nice, clean skin.

Relic

Relic - anonymous  Relic - editor

Ugly, amateurish skin. Needs a lot of work to get it into something usable. Probably you're better looking for something else.

Sonia

Sonia - anonymous  Sonia - editor

Not a GHOP, it just sits in the Collective svn repository. Promising, but would need a lot of customizations to make it work.

Conclusion: the problem remains: there are very few community-produced plone skins, and the ones available are usually low quality. We, the community, have got to do something about this.

Note: I have no affiliation to any of the GHOP students, mentors or the Plone - GHOP project.

2008-03-13

Tutorial: run ArchGenXML 2.0 under virtualenv

Filed Under:

The "modern" (post 1.5) version of ArchGenXML is packaged as egg, available on pypi. While in theory you could run "sudo easy_install archgenxml" and have it running with minimal effort, because it depends on zope.component and zope.configuration, things tend to get muddy and complicated. If you'll "easy_install zope.component" you'll get a bunch of zope eggs installed in python's site-packages and this will probably cause problems. When I've started developing with Zope 3 I had some hard time tracking some problems that ultimately turned out to be caused by zope packages installed in the system python "conflicting" with my regular zope instances. Even the Plone installer prefers to create its own Python directory, to keep the its packages separated from other python packages installed in the system. To solve this problem, ArchGenXML has a mechanism to specify a path to the zope packages, of which I've already blogged about, but I now consider it an extra step which can be avoided by using virtualenv to install the archgenxml egg.

This following recipe is specific to Ubuntu, but probably adaptable to any Linux system, and even Windows. First, if you don't have easy_install in your system, install it with:

#sudo apt-get install python-setuptools
#easy_install virtualenv

In my ~/Software folder I've ran:

#virtualenv agx

This will create a ~/Software/agx virtual environment. We need to activate it:

#source agx/bin/activate

Now all python commands we will run (python, easy_install) will 'belong' to this virtual environment. We can safely install agx, zope.component and zope.configuration, as they will be installed there:

(agx)#easy_install archgenxml
(agx)#easy_install zope.component
(agx)#easy_install zope.configuration

The ArchGenXML egg has defined several console scripts, they're available as scripts "tied" to this virtual python environment, for example, this is the 'archgenxml' script that was installed in my ~/Software/agx/bin folder:

#!/home/tibi/tmp/arch/bin/python2.4
# EASY-INSTALL-ENTRY-SCRIPT: 'archgenxml==2.0-rc1','console_scripts','archgenxml'
__requires__ = 'archgenxml==2.0-rc1'
import sys
from pkg_resources import load_entry_point

sys.exit(
load_entry_point('archgenxml==2.0-rc1', 'console_scripts', 'archgenxml')()
)

What this tells us is that you can safely run this script from "outside" the virtual environment, without needing to first "source bin/activate" it.

2008-01-31

The 763 projects in the Collective SVN

Filed Under:

Today I was curious about the number of projects found in the collective svn. They always seemed a lot, but I never knew how many. Until today, when I ran a xpath query over the subversion page and I found that there are 763! This number shocked me, I was expecting at most 200. My number of projects there is very small though, I can only claim ownership over 2 of them.

2007-02-11

First glance at Plone 3

Filed Under:

Thanks to the easy plone 3 buildout (plonout), I'm having my first look at the upcoming Plone 3. Some of the more evident changes:

  • Versioning is now possible thanks to CMFEditions, which means a "Save as version" option in the edit screen and a "Versions" page on objects.
  • The Kupu integration has been improved, the Kupu configlet offering new functions: the possibility to edit the toolbar, a new, streamlined interface to control the resource types and the possibility to replace the reference browser with a kupu drawer. In the edit screens kupu now has an "Anchor" button, which allows anchor insertion.
  • The interface hasn't changed at all, at least looking at its surface. Would this mean easy transition from older 2.1 - 2.5 sites to the new Plone 3.0?
  • wicked is integrated, meaning you can get easy wiki-like behaviour, "without the aftertaste of wikis"
  • The calendar has now a configlet, offering the old ZMI options accessible until now in portal_calendar
  • A configlet to specify the default mimetype for editable text fields (Types Settings)
  • The 'sharing' tab is back, with an improved interface
  • The different views on objects are loaded through AJAX and there's a "Loading" OSD that appears at the bottom of the page
  • In the Edit screen there is a "toolbar" at that top that uses AJAX to load several views that gather different settings that were spread among the Edit and Properties screens until now.
  • There is now a portlet management engine which allows portlet customizations. To me, at first look, this management page seemed extremely crowded and unintuitive. But this was just the first impression, after a minute of playing I already felt comfortable with it. Unfortunately, there's no "Simple HTML portlet", an option already offered by other portlet engines such as CMFContentPanels and the "Classic portlet" required knowing a template path and a macro nameb, but I'm sure this "Simple HTML portlet" is something that could be easily written. On the plus side, the portlet management engine offers the possibility to place portlets only for a specific group or for specific content types, which couldn't be easily done using CMFContentPanels.
  • There is a "rules" option in the action menu on the main page, which leads to several pages that allow defining actions based on conditions, but I couldn't get it to do much and didn't insist on it.

A lot of new, exciting stuff, without even looking under the hood (Zope 2.10, lots of zope 3 technology used, KSS and Ajax). I've encountered several bugs and there are several areas that could be improved, so it would be great if more people would download the ploneout and run Plone 3.0, at least to have a look, play with the new technologies and report the bugs. 

I presume that upgrading Plone 2.1/2.5 to Plone 3 would be relatively easy if there weren't many customizations done to the management interface, but this new technology also adds to the complexity of the Plone as application development framework. One last thing, if you haven't learned Zope 3 by now, start right now, it has become unavoidable in developing for Plone 3.

2007-02-06

Better load time for Plone sites

Filed Under:

You probably know by now that Plone sites are better suited at content creation that content delivery. Still, the Plone solution is too good to pass even when creating simpler sites, where +99% of the trafic will be anonymous one. And when you have a good hammer, everything looks like a nail.

One of the various problems that Plone has when delivering this brochure type of websites is that the page weight is pretty high. On an average page that loads some images (a logo and a splash image), a Plone page can weight at about 500 kb. Pretty high, especially when the page doesn't seem too "different". The Javascript files loaded for this page are about one third of its weight and probably not used, if your website doesn't use the livesearch, search engine word highlight, internal search word highlight, the icons for external links or any other "gimmicks" that Plone uses to enhance the user experience.

To prevent these files to load for the anonymous user, place the following condition for the undersired javascript files in portal_javascripts:

python: not portal.portal_membership.isAnonymousUser()

In my case, after some testing, I've decided to leave the following files untouched, to make it possible for site editors to login from the site:

register_function.js
plone_javascript_variables.js
cookie_functions.js
login.js

Next, a look at the css files that are being loaded will show some possibility for improvement there as well, but not as dramatic. Many of the files there can be conditioned with the same line as above, but this depends on the type of website being developed.

You can enable the debug mode for both portal_javascripts and portal_css to help observe which file gets loaded. Of course, placing those conditions in portal_javascripts and portal_css will probably most likely increase the load on the server, but the trade-off is probably worth it.

And finally, enabling mod_cache and mod_deflate for the website will help even further reduce the number of bytes needed to be loaded from the Plone site.

2007-01-30

Problems with migrating AT content from Plone 2.0 to Plone 2.5

Filed Under:

Latest problem that ate too much of my life already (took me a night to get through) was importing some content from a Plone 2.0 site to a new instance of Plone 2.5. The old content was created using an old version of AT (probably 1.2). To prepare the migration I've created a new content type using ArchGenXML that mimicked the old product name, classes and fields and exported the content from the old Zope instance as a .zexp file.
The process should have been pretty much straightforward, but I hit some problems: the content types for the objects and fields was broken (it was printed as <plain_text at broken>). I had to write a script (which used an ExternalMethod library that I used to examome objects) that changed the content type to text/structured and text/plain on several fields. Next, there were lots of unicode decoding problems that made impossible cataloguing the content. So I ran again a script to convert that content and finally things started to look right.

I believe the problem with the invalid content type was due to the fact that the mime_types package from MimetypesRegistry was refactored (moved or replaced) since Plone 2.0 was released with Archetypes 1.2.

2007-01-12

Firebug getting close to 1.0

Filed Under:

Wow! I am impressed. Following a discussion on slashdot I've installed the new 1.0 beta version of Firebug, an extension for web developers. Created by the same author as the classic Dom Inspector, Firebug didn't seem too useful for me until now. The version on the mozilla extensions site is old (0.4), not so featured and to me it seemed to be really buggy. The new version seems to work very good and offers for each area of focus a multitude of information and options that puts it on first place in my toolkit as Plone web developer.

2006-11-07

Getting the parent object in an acquisition context

Filed Under:

To get the parent of an object, you'd have to use this code:

myparent = aq_inner.aq_parent.aq_self

2006-10-22

Bulk modifying AT content fields under restricted python scripts

Filed Under:

I'm working on a project that mostly extends an older, legacy based Plone 2.0 project. This project has a CMFFormController form with about 20 fields and based on that input needs to create new AT content items, which is done in the action script of the controller chain. To achieve this, I have the following code:

First, I have a field_mapping that maps the fields from the form to the AT field names. Based on this mapping, I'm retrieving the value from REQUEST and set it back in the mapping (the form generation changes the field names to concatenate with a session id, in order to save the already submited values in a session, as far as I understand).

    #write the values into the above dict
    for key in field_mapping:  
        field = request.get('%s_%s' % (field_mapping[key], sid))
        field_mapping[key] = field

The form also has some field upload fields, which I'm handling with this code:

    #handle the empty file uploads
    for f in ['file1', 'file2', 'file3']:
        fupload = request.get(f, None)
        fname = getattr(fupload, 'filename', '')
        if fname.strip() <> '':
            field_mapping[f] = fupload

In the end, I'm calling the mutators for each field to set the values to those retrieved from REQUEST.   Calling Schema[fieldname].set() is impossible to do from the restricted Python script because of the security settings.

    schema = myobj.Schema()
    for fname in field_mapping:
        field = schema[fname]
        mutator = field.getMutator(proposal)
        mutator(field_mapping[fname] )

I've first tried to pass the field_mapping as **field_mapping argument to the plone_utils.contentEdit method, but it doesn't seem to update AT based objects, just the attributes.

Weblog
Atom
RDF
RSS 2.0
Powered by Quills
Technorati
Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 License.
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: