Netsight Blog

Cool stuff Netsight are up to in Zope and Plone

Blog > Entries tagged ploneconf2010

[The code below has now been update to reflect the advice from Martin in the comments below]

Plone 4

A few people have asked recently if Plone 4 is ready for production use yet, and so I thought I'd share the experiences of developing the Plone Conference 2010 website, which is running Plone 4.0b3.

The short answer seems to be 'yes'. The longer answer probably depends on if you are starting from scratch on a new project or upgrading an existing Plone 3 site. There are a number of 3rd party Plone products that still need further testing on Plone 4, but I'm please to see that the ones I tried all seemed to work.

Not only are we using Plone 4, but we are also using Dexterity (1.0b1), the new content types system for Plone; PloneGetPaid (0.9.1), the e-Commerce system for Plone; and plone.app.caching (1.0a1), the replacement for CacheSetup which enables Plone to work nicely with HTTP caches such as Varnish (which we are using here). All of these are the released versions from pypi, so no SVN versions needed, and work very well together. So we really are 'eating our own dogfood' here and whilst it might seem a bit scary to be on the cutting edge for a production site, the whole experience has been very good.

Plone 4 is lightning fast, and all the hard work put in by the community really makes it a joy to work with. Restarting Plone during development is much quicker than with previous versions of Plone.

If fact we are using a combination of both Dexterity and Archetypes on this site. All the regular content on the site (folders, news items, pages, images, etc) are Archetypes based, but the content types for the registrations system are Dexterity based. Why? Because the site was developed by two people, and one wanted to stick to Archetypes as that was what they were familiar with, and the other person wanted to give Dexterity a try. Both run side by side just fine.

The Registration System

My goal for the registration system was to make it as simple and user-friendly as possible. So many times previously I have registered for conferences in which the registration system is so convoluted. I especially hate it when I need to register four or five people from Netsight and I have to register each person separately and enter my credit card details over and over again for each registration. One particular European python conference can't handle the credit card owner and the attendee being separate people and so you have to abort the registration process half way through for each attendee, wait for an email to be sent (to the attendee, which they then have to forward to you) with the registration reference number in, you have to phone them read out each reference number and manually process the order!

So I was determined to make this better. I hope I've succeeded. And if you are a person that has to register multiple people for the conference, I hope you appreciate this attention to detail and you can buy me a beer ;)

The reason we tried Dexterity for the registration content types was so that we could easily create a custom 'add' form using z3c.form. By using plone.directives.form we were able to really easily create a custom form which would allow us to tailor the form layout better ie we could easily change the usual 'Save' button which we would have when adding Archetypes based content to Plone to a 'Register' button. We are also able to use Fieldsets from plone.supermodel.model to group our fields together into specific fieldsets to improve the readability of the form.

Using a z3c.form also makes it easier to allow anonymous users to create 'Attendee' objects on the site -- which is how our registration system works:

When someone clicks the 'register' link on the site, it takes them to a custom z3c.form generated form for the Attendee content type. The user fills in their details and hits 'register' this causes an Attendee item to be created in a specific folder in the site, and the item to be then added to the GetPaid shopping cart and takes the user to the cart view page. The user can then register additional people, if they want, before being taken to Paypal to pay for their registration (using getpaid.paypal). Once the payment is successful, Paypal makes a callback to the site which causes GetPaid to transition the order from 'Charging' to 'Charged' state and in turn transition all Attendee objects in that order to the 'Paid' state. The code is really quite simple. First we define our interface for out Attendee object, this is where we define the schema of the object:

# attendee.py
from five import grok
from zope.schema import TextLine, Choice, Bool
from plone.directives import form, dexterity
from netsight.ploneconf2010_registration import _

class IAttendee(form.Schema):
   """A conference attendee"""

   ### Contact details

   firstname = TextLine(
       title=_(u"First Name"),
       )

   lastname = TextLine(
       title=_(u"Last Name"),
       )

   city = TextLine(
       title=u'City',
       required=True,
       )

  shirt = Choice(
       title=u'Plone Conference 2010 T-Shirt size',
       required=True,
       vocabulary="netsight.ploneconf2010_registration.shirts"
       )


#..... further fields omitted for brevity

Then in browser/registration.py we create our custom registration form:

from five import grok
from plone.directives import form

from z3c.form import field, group

from netsight.ploneconf2010_registration.interfaces import IRegistrationFolder
from netsight.ploneconf2010_registration.attendee import IAttendee
from netsight.ploneconf2010_registration import _

class ContactGroup(group.Group):
    label=u"Contact Details"
    description=u"Enter your contact details below"
    fields=field.Fields(IAttendee).select(
        'firstname', 'lastname', 'city', 'postcode', 'country', 'email',
        )

class PreferencesGroup(group.Group):
    label=u"Preferences"
    description=u"Let us know of any dietry requirements you have, t-shirt size and if you will be attending the sprints"
    fields=field.Fields(IAttendee).select(
        'food', 'food_other', 'shirt', 'sprints',
        )


class RegistrationForm(group.GroupForm, form.Form):
   grok.name('registration')
   grok.require('zope2.View')
   grok.context(IRegistrationFolder)

   schema = IAttendee
   ignoreContext = True

   label = _(u"Register for Plone Conference 2010")
   # we want to further customise the form...
   template = ViewPageTemplateFile('templates/registration_form.pt')

   # Group the fields into fieldsets, only included a few for brevity
   groups = (ContactGroup, PreferencesGroup)

   # We want the fieldsets presented one below the other, not in tabs
   enable_form_tabbing = False

   def update(self):
         # disable Plone's editable border
         self.request.set('disable_border', True)

         # call the base class version - this is very important!
         super(RegistrationForm, self).update()

   @button.buttonAndHandler(_(u'Register'))
   def handleApply(self, action):
         data, errors = self.extractData()
         if errors:
             self.status = self.formErrorsMessage
             return

         # Create the attendee object in the attendees folder
         # setting checkContraints to false means we skip the security checking and allow anon to add
         attendees = self.context.attendees
         attendee = createContentInContainer(attendees, 'netsight.ploneconf2010_registration.attendee', 
                                           checkConstraints=False, **data)

       # Add attendee to shopping cart
       self.addToCart(attendee)

       portal_url = getToolByName( self.context, 'portal_url').getPortalObject().absolute_url()
       return self.request.response.redirect('%s/register/@@getpaid-cart' % portal_url)    

I wanted to add a chunk of HTML at the start of the form, with a table of prices and instructions on payment options, so I created a custom template referred to in the form with the HTML in templates/registration_form.pt

<html xmlns="http://www.w3.org/1999/xhtml"
     xmlns:metal="http://xml.zope.org/namespaces/metal"
     xmlns:tal="http://xml.zope.org/namespaces/tal"
     xmlns:i18n="http://xml.zope.org/namespaces/i18n"
     i18n:domain="plone.z3cform"
     metal:use-macro="context/main_template/macros/master">

   <metal:block fill-slot="main">

       <h1 class="documentFirstHeading" tal:content="view/label | nothing" />

       <img src="http://farm4.static.flickr.com/3505/4074083883_797e6c371f_m.jpg"
            align="right" width="240" height="169" alt="Plone Conference 2009 delegates" />

       <p>To register for Plone Conference 2010, fill in the registration form below.
         If you are registering a number of people then you will have a chance to add
         multiple registrations to your cart before checking out to pay.</p>

       <!-- more HTML -->

      <div id="content-core">
           <metal:block use-macro="context/@@ploneform-macros/titlelessform" />
       </div>

   </metal:block>

</html>

This give me the flexibility to add extra stuff to the form, but to retain all of z3c.forms machinery for generating the form from the IAttendee interface and to do all the validation and checking of mandatory fields. You may notice that I set the view to be registered to IRegistrationsFolder, read my previous blog post for an easy way to set the default view on an arbitrary folder.

A further refinement to the Attendee object was to get it to be able to return a title from the first and last names entered. Due to Plone using the catalog for folder view listings, and for legacy reasons it looks for an attribute or method on an object called 'Title' we needed to add this method to our class. So the extended version of the attendee class is:

# attendee.py
from five import grok
from zope.schema import TextLine, Choice, Bool
from plone.directives import form, dexterity
from netsight.ploneconf2010_registration import _

from plone.app.content.interfaces import INameFromTitle
from plone.dexterity.content import Item

class Attendee(Item):
   """ An attendee """

   def Title(self):
       """ return the title """
       return INameFromTitle(self).title


class IAttendee(form.Schema):
   """A conference attendee"""

   ### Contact details

   firstname = TextLine(
       title=_(u"First Name"),
       )

   lastname = TextLine(
       title=_(u"Last Name"),
       )

   city = TextLine(
       title=u'City',
       required=True,
       )

  shirt = Choice(
       title=u'Plone Conference 2010 T-Shirt size',
       required=True,
       vocabulary="netsight.ploneconf2010_registration.shirts"
       )


#..... further fields omitted for brevity

class TitleAdapter(grok.Adapter):
   grok.provides(INameFromTitle)
   grok.context(IAttendee)

   def __init__(self, context):
       self.context = context

   @property
   def title(self):
       return '%s, %s' % (self.context.lastname, self.context.firstname)

By registering an adapter for INameFromTitle is means that the object creation mechanism can look up what the title of the object is, and then convert that to a more meaningful id for the object created.

GetPaid

This was the first time I'd looked at GetPaid, and credit to all the people who have worked on it, it really is a fantastic product. Previously we have always ended up coding our own eCommerce products for Plone from scratch as every customer's requirements have been different enough to make using any of the existing shopping cart systems for Plone difficult. They always seemed to have made assumptions about a particular country's tax or shipping system that didn't work for us. And making small changes always ended up in us subclassing the entire system, which was a pain. GetPaid uses the Zope Component Architecture to the full and the ability to simply mark any regular piece of content as buyable makes building stores with Plone a breeze.

Imagine you wanted to create a shop online that sold jewellery. With just stock Plone and PloneGetPaid installed you could simply upload photos of each jewellery piece using the standard Plone image content type, and set the folder to thumbnail view. Then mark each image as 'buyable' and give them a price and stock code and you are done. Add getpaid.paypal and configure a Paypal account in a few minutes and you can now accept payment. No custom coding needed whatsoever. No merchant account needed. Combine that with collective.xdv and a free theme from one of the free template sites, and you are set.

Conclusion

This was the first time I've actually used z3c.form from within Plone, and combined with Dexterity it provides a very powerful system which makes it very easy to quickly develop content types and really nice flexible forms for them. I'm looking forward to using this combination in future Plone projects. The only area where Archetypes still leads is the number (and polish) of some of the widgets, but I think that z3c.form is catching up quickly. Porting over some of the more complex Widgets from Archetypes to z3c.form would be a fantastic sprint topic, and if no-one gets there beforehand, I'm going to raise it as a topic for the sprint after the Plone Conference.

Plone 4 really is amazing, and the best version of Plone yet.

See you at the Plone Conference 2010 in Bristol! Registration is Open!

-Matt

Well, we have about seven months until the Plone Conference rocks up in Bristol in October, and we've been busy securing the venue.

I am now proud to announce the Plone Conference 2010 will be held at the 4* Thistle Grand Hotel in central Bristol.

Thistle Grand Hotel

The hotel is located in the central old part of Bristol City, with its cobbled streets and old buildings. We have four rooms booked in the hotel for the main conference, the largest holding 400 people, the others holding around 90 people each. The hotel also can offer us around 60 rooms for delegates to stay in during the conference, and there is a wide number of other hotels of various costs, serviced apartments and youth hostels in walking distance.

http://www.netsight.co.uk/news/images/full_thistle_bristol_m_e_wessex.jpg

There is also plenty of social life around with a large number of restaurants, bars and clubs within a few minutes walk. All delegates will also have passes to the hotel's leisure centre as well.

http://www.netsight.co.uk/news/images/full_thistle_bristol_hotel_swimming_pool.jpg

But beyond all that, this hotel actually has quite a nice historical connection with what we are doing -- a connection I only discovered when searching for photos for this blog post.

Our main aim with the work we do with Plone and on the internet in general mostly revolves around communication. We allow others to communicate information better. Whether that be by designing public facing websites, private corporate intranets, or group collaboration spaces... we enable communication.

The White Hart and White Lion Inns

The Thistle Grand stands on the site of a previous important link in the world of communication -- the mail. Before the Grand Hotel there stood the White Hart and White Lion Inns. Looking at the lithograph above and the modern photo at the top you can see the same church tower behind the site of the venue. The White Lion Inn can be traced back to 1606 as an Inn and went on to become a very important part of the Kings Post:

"The White Lion, Bristol, was one of the most 
famous coaching houses in England, east, west, 
north, or south. It stood in Broad Street, a 
thoroughfare which belied its name as regards 
breadth, and could only be considered broad by 
comparison with the even narrower Small Street, 
which ran parallel with it. Yet at one time 
there were as many coaches passing in and out 
of Broad Street as any street in Bristol, or 
even in London!"

This excerpt it taken from a book originally published in 1905 entitled "The King's Post -- Being a volume of historical facts relating to the Posts, Mail Coaches, Coach Roads, and Railway Mail Services of and connected with the Ancient City of Bristol from 1580 to the present time." published online by Project Gutenberg.

Back then, with no telegraph or telephone (or even internet!) Bristol used to even have its own time, being 2 degrees 30 minutes west of London it was approx 10 minutes behind London on time, evidence of which can still be seen on the clock above the Corn Exchange in the centre which has two minute hands, one for London and one for Bristol:

Bristol Time

With the advent of the railway, and Bristol's famous son, Isambard Kingdom Brunel who build the Great Western Railway, Bristol Time was subsequently abolished and Railway Time adopted in 1852.

Anyway, that is the history lesson over. The main thing to be excited about is we have a venue :)

We are now currently selecting a venue for the conference dinner/party and our shortlist includes a former railway terminus (the world's earliest surviving purpose built railway terminus), an art gallery, a victorian bank, and an arts and media centre. We just need to work out which one will work out best for us!

As for talks, training and all that... We'll be putting a call out for training proposals and talk submissions once Plone Symposium East and European Plone Symposium are out of the way. We will be opening booking for the event in June.

-Matt

Well, we've finally done it! For a number of years now at Plone conferences around the world, I've said "Wouldn't it be great to hold the Plone Conference in the UK?' and each successive year I seem to say it after fewer and fewer beers. This year, we've finally done something about it, and put a bid in to host the Plone Conference 2010 in the UK. Not only that, but the bid was accepted :)

So now comes the hard work, in terms of planning the whole event. I think if we get things started nice and early then we should be OK. So far I've been in touch with a number of previous Plone Conference organisers and got quite a good deal of feedback from them on things that worked or didn't work from their point of view with the management and running of the conference. Having been to every conference except the first one myself, I've got a pretty good idea of what makes them work from a delegates point of view (decent wifi and lots of coffee! ;) ).

Bristol's Biggest Bike Ride - credit: http://www.flickr.com/photos/pshab/

Bristol's Biggest Bike Ride. Bristol is the UK's first 'Cycle City' and is known for its work on environmental issues. This photo is taken in front of @Bristol, a science museum. The big silver dome is the planetarium. Those that came to the Performance Sprint in Bristol might recognise it, as was just around the corner from the sprint venue.

Bristol is a fantastic city, located in the South West of the UK with a population of around 600,000 people. Despite its modest size, it has a very high regard with technology and media. The BBC Natural History unit is here, and a lot of BBC Dramas filmed in the city, and around this spawned a whole ecosystem of related media businesses such as post-production, graphics, audio, costume, etc. When the term 'New Media' started to surface in the early 90's Bristol was hot on the scene and as a result a large number of digital / interactive agencies formed. Bristol is also home to Aardman Animations, the creators of Morph, Wallace and Gromit, Shaun the Sheep and other well known plastercine characters. Bristol is also referred to as the 'Silicon Valley of the UK' with a whole host of silicon chip manufacturers and related businesses here.

Bristol Cathedral (foreground) and Bristol University (behind) - credit nicksarebi http://www.flickr.com/photos/34517490@N00

Bristol Cathedral in the foreground and the Wills Memorial Building, part of the University of Bristol in the Background. The University received its charter in 1909, and is now one of two universities in the city -- the other being the University of West England. This building was built between 1912-1925 and considered one of the last great Gothic buildings to be built in the UK.

I came to Bristol in 1996 to attend the University of Bristol to read Computer Science, and graduated four years later to form Netsight, based just over the road. in the next 10 years, Netsight has grown to 13 staff and become well known within the Plone community for our advocacy work, and promotion of Plone.

Each year, the Plone Conference gets better and better, so I'm under no doubt that I have some pretty high expectations to meet. Last year I was leading the programme committee for the Budapest conference and we had an amazing number of talk submissions, way more than we had room to fill and we had a tough choice picking the talks. This year I want to get direct feedback from the community and get the talks organised earlier and get them all up online so the whole community can see them and vote on the talks they would most like to see. That way we can be as transparent as possible, but also make sure that we give a chance to those potential delegates that are not yet so involved with the Plone community to have a vote in which talks they want to see. It is always hard to make sure we get a good balance of talks for those new to Plone and those with lots of experience. It will also give us a chance to gauge the talk popularity beforehand and schedule the talks in the appropriately sized rooms.

Speaking of rooms, yes we do have a venue already in mind. We are talking to more than one and just negotiating the final details with them before we make it concrete and announce the venue.

One item you might have seen on the preliminary conference page is the one-day 'Analysts / Customers / Suits' mini-conference. The goal of this day is to attract those people whom we might not normally reach so easily as a (generally developer-focused) community. For this I'm talking about industry analysts and pundits, journalists, technology evaluators, customers, etc. I don't mean to be glib when I say 'suits' but hopefully most people will get what I mean. The main conference has always historically been very inward focussed as a community. Events like World Plone Day have shown the value of reaching out to a wider audience and I see the conference as an ideal time to organise something. This was if someone wants to they can come to the one-day conference and stay for the main conference as well. For the one-day event I'm hoping to invite a number of speakers to come and present case studies of Plone projects they have been involved in.

I'm open to ideas as well for all aspects of the conference. If you have any particular ideas you'd like to see, or want to get involved in the conference then by all means drop me an email on ploneconf2010@netsight.co.uk. I'm going to me asking around the community for volunteers (esp. from the other UK Plone companies) as well closer to the time.

-Matt