What is gen ?

gen is a code generator that allows you write web apps without having to face and understand the plumbery of a given web framework. gen protects you. Concentrate on functionalities that need to be implemented: gen will fight for you against the low-level twisted machineries and will let you evolve in your pure, elegant and minimalistic Python world.

Download and install

As a prerequisite, your machine must be able to compile. If it is not the case, install the necessary packages. On Ubuntu, for example:

sudo apt-get install build-essential

Install Zope 2.9. On Unix/Linux, the easiest way to do that is to download the Plone unified installer, that includes Zope.

tar xvfz Plone-2.5.5-UnifiedInstaller.tgz
cd Plone-2.5.5-UnifiedInstaller
./install.sh

Don't be afraid, you just installed a lot of lines of code, but we will only use a very small subset of it: absolutely no line from Plone, a tiny subset of Zope and the Python interpreter that was also included.


Install Appy. Download it here, unzip it and install it in the Python interpreter previously mentioned.

unzip appy0.8.1.zip
mv appy /opt/Plone-2.5.5/Python-2.4.4/lib/python2.4/site-packages

Create a symbolic link, in /usr/bin, of your Python interpreter.

ln -s /opt/Plone-2.5.5/Python-2.4.4/bin/python2.4 /usr/bin/python2.4

Create a Zope instance. A Zope instance is a web server that will listen for browser requests on some port. Launch the script named mkzopeinstance.py that is included with Zope. The following lines of code create a Zope instance in /home/gdy/instances/RegInstance.

python2.4 /opt/Plone-2.5.5/bin/mkzopeinstance.py
[answer script's questions:]
Directory: /home/gdy/instances/RegInstance
[also: username and password of the admin]

Type anything as username and password: Appy will ignore it and create user admin, password admin.

Your instance is ready! It will run on port 8080 by default.

Create a webapp

Now, we need to write a webapp and install it into this instance. We will create a small webapp, called Registration, that will allow anonymous people to register to the Appy webapp awards and propose a webapp. The administrator of the awards will be able to consult and search registrations.


An Appy webapp is simply a Python package. So create a Python package, for example in /home/gdy/projets/Registration.

cd /home/gdy/projets
mkdir Registration
cd Registration
touch __init__.py
touch Registration.py

File __init__.py is required by Python, to tranform folder Registration into a Python package. File Registration.py will contain the definition of the class Registration: one instance of this class will be created and stored in the database every time a user registers itself though the web.

# ------------------------------------------------------------------------------
from appy.gen import *

# ------------------------------------------------------------------------------
class Registration:
    root = True
    creators = ['Anonymous', 'Manager']

    p = {'multiplicity': (1,1)}
    applicantName = String(**p)
    applicantEmail = String(validator=String.EMAIL, **p)
    companyName = String(**p)
    companyUrl = String(validator=String.URL, **p)
    webappDescription = String(format=String.XHTML, **p)
    companyDescription = String(format=String.XHTML, **p)
# ------------------------------------------------------------------------------

This class is declared as root: for the moment, just remember that it gives it a special, first-class status. One line below, we define the roles that are allowed to create instances of this class. Anonymous and Manager are 2 standard Appy roles. The remaining lines define the attributes of every registration. Dict p is simply a shorthand for specifying the same (group of) attribute(s) to several methods.


Now that we have developed a complete webapp (yes, it is already over! Be patient, in a second iteration we will improve it), we need to plug it into the Zope instance.

Plug the webapp into the Zope instance

Zope requires a bit more than our 11-lines file to consider it to be a serious webapp. So gen includes a script that will generate a so-called "Zope product". Create, in your app, a file named generate.sh with the following content.

#!/bin/sh
python2.4 /opt/Plone-2.5.5/Python-2.4.4/lib/python2.4/site-packages/appy/bin/generate.py . -s

Make it executable and execute it (ensure you are in folder Registration).

chmod a+x generate.sh
./generate.sh

You should get something like this.

Appy version: 0.8.1
Generating Zope product in /home/gdy/projets/Registration/zope...
Generating Registration.Registration.Registration (gen-class)...
Done.
Python: 2 files, 16 lines (19% comments, 12% blank)

Now, in your webapp, you have 2 more folders: zope and tr. Folder zope contains the "product" as required by Zope, while tr contains i18n (internationalization) files: forget about it for the moment. We can now link the webapp to the Zope instance by creating 2 symbolic links.

cd /home/gdy/instances/RegInstance/lib/python
ln -s /home/gdy/projets/Registration .
cd /home/gdy/instances/RegInstance/Products
ln -s /home/gdy/projets/Registration/zope/Registration .

The first link allows the Zope instance to import your Python package, while the second one allows Zope to realize that he must take care about a third-party plug-in.

Play with the webapp

Launch now your Zope instance:

cd /home/gdy/instances/RegInstance/bin ./zopectl fg

You should get something like this (with additional lines if it is the first time you launch the instance).

/home/gdy/instances/RegInstance/bin/runzope -X debug-mode=on
2012-09-13 16:07:58 INFO ZServer HTTP server started at Thu Sep 13 16:07:58 2012
  Hostname: 0.0.0.0
  Port: 8080
2012-09-13 16:07:59 INFO Registration is being installed...
2012-09-13 16:07:59 INFO Registration Appy version is "0.8.1".
2012-09-13 16:07:59 INFO Registration Translation "en" updated from "Registration-en.po".
2012-09-13 16:08:01 INFO Zope Ready to handle requests

Open a browser and go to http://localhost:8080. You should something similar to this.


Congratulations! Now, let's create a new registration by clicking on the "plus" icon. You should get this form:

...


Of course, it was deduced from our class Registration. Notice that an additional field, named title, has been automatically added. Indeed, this field is of special importance to Appy, so is added if not explicitly defined. Of course, we will see that it is possible to hide it and compute it automatically, or simply to label it differently, but for the moment we will simply consider that it corresponds to the name of the webapp proposed by the user. Fields defined as Strings with format=String.XHTML are rendered with ckeditor, an popular on-line editor integrated within Appy.


If you do not complete the form correctly, you will get validation errors.


In this example, I have entered an email with a wrong format (remember, a validator String.EMAIL was defined) and I entered no value for a mandatory field. multiplicity=(1,1) means: at least and at most one value is required.


Once validation succeeds, the registration is stored in the database and the user can visualize it: