4 posts tagged “lajornada”
Lightning Talks are among the best investments of time you can make on any Plone Conference: there's always a lot of smart people doing great things.
During the Plone Conference 2007, in Naples, Florian Schulze spoke about schemaxtender, a package that allows you to inject new fields into an Archetypes schema using an adapter. When I saw his talk, I knew I was going to use it for what I had in mind.
As I mentioned in a previous post, in La Jornada we were looking for a way to adapt Plone's standard News Item content type to:
- add new fields to it (property, section, urgency and byline)
- change fields' order among different schematas to make the edition of new content easier for the publishers
Using schemaextender to accomplish these tasks was so easy that I was really
excited when I finished. I spent about 40 hours (in fact, a little bit more after the second release) to read
Part 1 of Philip von Weitershausen's excellent book on Zope 3, to
understand the way schemaextender works, to find out how to make it work on Plone 2.5, to start using the adapted content with Smart Folders, and even to write some tests for it.
All this work is available in a product called nitf4plone in case you want to try it (be aware this is an beta release). The product works on both, Plone 2.5 and Plone 3.0.
Let's analize the code... but first, a disclaimer: don't try this on Plone 2.5.
Why? schemaextender was written to work with Archetypes version 1.5 or later (that's, Plone 3.0 and later). There's a branch to make it work with Plone 2.5 patched by Erik Rose of the WebLion Project Team at PSU, but it will never be merged into the maintenance one. If you use this branch you are on your own in the event of a bug. Also, have in mind that there's no way back on doing this and after installing schemaextender in Plone 2.5, the adapter will be available for all sites in the instance.
So, yes, do as I say, not as I did. Having warned you, let's dive a little bit into the code.
schemaextender includes 3 types of adapters:
- ISchemaExtender lets you can add new fields to a schema
- IOrderableSchemaExtender lets you add new fields and reorder them
- ISchemaModifier is a low-level hook that allows direct manipulation of the schema
You can find information and examples on all of them on the source code. As you might have expected, I decided to use IOrderableSchemaExtender.
To write the adapter, we need to declare the new fields first; let's take a look to the section field as an example:
class SectionField(ExtensionField, atapi.StringField):
"""Named section of a publication where a news object appear
"""def getDefault(self, instance):
...
return nitf.default_sectiondef Vocabulary(self, instance):
...
return atapi.DisplayList([(x, x) for x in nitf.sections])
As you can see, we need to subclass from ExtensionField and StringField; please note that it's mandatory to keep this order. ExtensionField will provide standard accessors and mutators which are not generated on the class. StringField will provide standard attributes and the widget for the field. Also we override getDefault() and Vocabulary() methods to set the default value and vocabulary.
Let's take a look to the adapter's class now:
class NITFExtender(object):
"""Adapter to add NITF fields to News Items
"""
implements(IOrderableSchemaExtender)
adapts(IATNewsItem)fields = [
...
SectionField('section',
languageIndependent=1,
enforceVocabulary=1,
required=1,
widget = atapi.SelectionWidget(
label='Section',
label_msgid='section',
description='Named section where the news object appear',
description_msgid='help_section',
i18n_domain='nitf4plone')),
...
]def __init__(self, context):
self.context = contextdef getFields(self):
return self.fieldsdef getOrder(self, original):
# we only need to change the order of the fields in Plone 2.5
if 'metadata' in original:
# first we remove the fields from whichever schemata they are
for schemata in original.keys():
if 'relatedItems' in original[schemata]:
original[schemata].remove('relatedItems')
if 'subject' in original[schemata]:
original[schemata].remove('subject')
# now we insert them where we want them to appear
idx = original['default'].index('property')
original['default'].insert(idx, 'subject')
original['metadata'].insert(0, 'relatedItems')
return original
As I mentioned, our adapter implements IOrderableSchemaExtender. In Plone 3.0 adapters can be registered locally at installation time:
sm = portal.getSiteManager()
sm.registerAdapter(NITFExtender,
(IATNewsItem,),
IOrderableSchemaExtender,
)
In Plone 2.5 we can't have local adapters and registrations aren't persistent, so we have to handle this in a different way:
Here you can see the way news items look after applying the adapter:
The code of the adapter is pretty clean and easy to understand.
Having finished it, we followed Mikko Ohtamaa's procedure to adding new fields to Smart Folders search in order to display all news articles for a given section and it worked fine.
Right now we are working on the migration of the content of our site to use the new fields; we are also preparing some templates to display the new information and some CompositePack's viewlets to use them to create the front pages in a better way.
Please let me know if you find this development interesting or if you want to participate in some way.
I want to thank all the members of the Plone community who helped me answering my questions at the #plone channel on IRC and the Product Developers forum, specially Martin Aspeli and Florian Schulze (who helped me with the schemaxtender internals and were really patient with me), Mikel Larreategui and Erik Rose (who helped me with the installer), Wichert Akkerman and Andreas Jung (who are always available answering all sort of questions on the forums).
Back in 1995, La Jornada was the first newspaper on Spanish language to have a web site. Over the years, the site evolved from static HTML files, written entirely by hand, to use some dynamic content creation in PHP, but the work involved on maintaining the content and structure was huge. We needed a change, so in 2005 we started looking for a CMS.
I asked La Mancha, a friend of mine who was one of the visionaries who brought the newspaper into the web, and he gave me 2 options: one was written in Perl and the other one, in Python. The choice was obvious for me, and we started looking for more information on Plone soon.
I wrote to the Enfold Systems' guys and they put me in touch with Carlos de la Guardia. In three weeks, Carlos gave us an introduction to the Python/Zope/Plone world and he started acting as a consultant for the development.
Those were the early days of Plone 2.1 and Archetypes was the way to go. Our idea was to create content types for everything: editions, current news, analysis, features, opinions... you name it.
We spent several months working on that and, I have to admit, our first tests were not very successful. We had many things to learn and very few experience in many topics.
In the middle of 2006 we had to create a microsite to cover the Mexican general election. We decided to use a plain-vanilla Plone instance with no funky stuff on it and just install a basic skin. The experience was so good that we started using the same system, with some minor changes, as the breaking news edition of the diary.
In late 2006, when we were about to restart the work, I traveled to Seattle for the Plone Conference 2006 and after assisting to Martin Aspeli's talk, I finally saw the light: the way we'd been working was fine... but there were better and easier ways to do it!
From content types to adapters was the new paradigm shift, and we wanted to embrace it as soon as possible. Unfortunately, we couldn't restart the work because we started experiencing performance issues as a result of the increasing traffic. We spent many months understanding and fixing the problems.
The main development has been in standby since then but we've been releasing some of our work slowly. We decided to move some of our products to the Collective in order to enhance collaboration.
I've been talking lately with Carlos about current trends on Plone and Zope deployment and we have now a better idea of what we want to implement in the near future.
Tunning Zope's ZODB performance can be a big challenge. Almost everything you can find on the web about it can be resumed on the following: use the Edisonian approach: trial and error discovery.
At La Jornada we are using ZEO to serve about 500,000 pages to more than 60,000 visitors everyday. Some weeks ago I noticed we were facing performance issues with the servers holding most of the ZEO clients of our installation: at peak times the load was so high that we were unable to serve some pages.
In the beginning I thought I had made a mistake with the amount of memory dedicated to the servers but, based on our previous experiences with the main server, I started investigating how to decrease CPU usage looking for bottlenecks using the usual Linux tools like vmstat and iostat.
I didn't found anything clear but, suddenly, I noticed that the clients on the main server were also acting strangely: one of them had a very high CPU usage while the other had almost none. I started looking for a mistake on the load-balancing configuration, but after some time I discovered that one of the ZEO clients had a value of 20,000 in the cache-size directive and the other, the one running smoothly, a value of 30,000.
I made the following change on the zope.conf file of all of my ZEO clients:
<zodb_db main>
cache-size 30000
<zeoclient>
...
</zeoclient>
mount-point /
</zodb_db>
After restarting them I was shocked with the results: a minimum increase on memory usage and an amazing decrease on CPU usage. You can see below the behavior of one of the servers in the previous month (the change in the configuration occurred at the middle of the graph):
So, talking about cache-size, how big is big enough? According to Chris McDonough's excelent presentation at the Plone Symposium 2005 in New Orleans: as big as you can make it without causing your machine to swap.
And, how many objects can we store given a certain amount of memory? According to Dieter Maurer, as the size of objects can vary unboundedly, this gives very imprecise control over the main memory used for the cache.
In our case, with about 700,000 objects in the ZODB, memory consumption is around 1GB on a cluster of 3 ZEO clients (with 4 threads and 30,000 objects in cache each one).
As we reserved 2GB for this server, we still have some space to grow up; we only need to find out some time to test it.
CompositePack is a beautiful piece of code written by Godefroid Chapelle. We use CompositePack at La Jornada to create the frontpage for the breaking news edition.
Some time ago I was asked to create a viewlet for a photo gallery and we started testing some gallery products to accomplish this task. We tried FriendlyAlbum, Plone SmoothGallery, plonegalleryview and, the best and most promising by far, Slideshow Folder.
All products had limitations that keep me away from using them as a base for my solution. I didn't wanted to create any new content type neither, so the approach I followed was this:
- use a folder as a container for the gallery; the name and description of the folder was going to be the title and introduction text for the gallery
- use Image as the content type for the photos; the name and description of every image was going to be the alternative text (the alt attribute) and caption of the photo
Having this in mind, I started analyzing how to integrate one of the many JavaScript libraries available to create the gallery. I wanted to use KSS, as this framework is on the way to become the standard on the Plone world, but I abandoned the idea soon. KSS is still on development and most of the current work is being done on the Plone 3.0 branch. The only thing I found for Plone 2.5 was a product named PloneAzax with a 1.0 release in Alpha state. PloneAzax was more like a demo of how AJAX would be used in Plone 3.0, than an usable product. Worst: it had some conflicts with CompositePack and I didn't wanted to mess with it.
After some research on the web I decided to use jQuery JavaScript Library. jQuery is fast and concise, and it lets you traverse HTML documents and handle events. From here all my work was pretty straightforward... well I had to fight a little bit with jQuery and IE, but that's another story.
I created the viewlet the usual way and I inserted the JavaScript code with the help of a Python script. To get the list of images in a given folder I used context.atctListAlbum(images=1). I took this idea from atct_album_view.pt, the page template used to view the images in a folder as small thumbnails. I registered the viewlet for Folder content type using a modified version of compositepack-customisation-policy.py and the JavaScript file using portal_javascripts, the JavaScript Registry.
The photo gallery is working fine on IE 6.0+, Firefox 1.5+, Safari 2.0+ and Opera 9.0+. Please note that only one gallery is allowed per page. It would be nice to add some effects, but that will have to wait.
You can see here the final versions of image_gallery_viewlet.pt and getSlideshowScript.py.
CompositePack rocks! I hope you enjoy it as much as I do.