plone

Create add-on

Overview file-structure

Minimum skeleton

mynamespace.myaddon     | The container-directory of the add-on.

    setup.py            | Register this directory to the Python-interpreter of
                        | the ZOPE-instance.

    mynamespace         | The namespace-directory of the add-on.

        __init__.py     | Makes this directory a Python-module and contains
                        | the lines for the namespace-magic.

        myaddon         | The base-directory of the add-on.

            __init__.py | Empty file, make this directory a Python-module.

            myfile.py   | Example-file: If it contained a method called
                        | 'myMethod', it would be importable of any other
                        | registered egg like this:
                        |    from mynamespace.myaddon.myfile import myMethod

Optional components

The ‘mynamespace.myaddon/mynamespace/myaddon’-directory can contain:

configure.zcml  | Register all following files and directories, here.

setuphandlers.py | Make an addon available to ZOPE-instance.

profiles        | Make an addon installable to Plone-site and generally
                | hold GenericSetup-xml-files.

skins           | The "old-school"-way, where resources like templates,
                | stylesheets, etc., live.

browser         | The "new-school"-way, where resources live.

content         | Holds the Python-files for defining custom content-types.

subscriber.py   | Subscribers listen to events, describe here what to do
                | when an event happens, e.g.: "An item has been added to the
                | site, notify admin about it via e-mail-notifica."

A tale about creating a Plone add-on

Preamble

TL;TR: For illustration-purposes the lines of this document beginning with ‘TL;TR:’ are followed by commandline refering to Plone-helper-scripts of the egg ‘adi.devgen’. If you execute the command given after ‘TL;TR:’, it will create all the files explained of the following chapter. There are many alternative helper-script-tools, however in case you want to use this tool, you can install it quickly like this of the commandline:

pip install adi.devgen

Structure of a minimal Plone-Add-on

TL;TR: devgen addBase mynamespace.myaddon

Just like Plone consists of more than 200 Python-eggs, a Plone-Add-On is also a Python-egg and an egg is a namespaced Python-module. Any egg will be available to the Python-interpreter of ZOPE. To make an egg installable in a Plone-site, it also needs a so called ‘profile’. The following will explain these terms.

Python-module

A Python module is a directory which contains at least one file which must be named __init__.py. The name is a flag for the Python-interpreter to recognize this directory as a module, meaning its path can be imported of other Python-scripts, e.g. assuming we have a directory called ‘myaddon’, which contains a file called ‘myfile’ and that file contains a defintion called ‘myDefinition’, you can import the definition of another Python-file like this:

from myaddon.myfile import myDefinition

Python-egg

A Python-egg is a namespaced Python-module, a namespace can be any name, but it should better not be taken already, in case you want to share your add-on with the world.

The reason for namespacing is foremost to exclude the possibility that two or more modules could have the same name (in this example called ‘myaddon’), as it would result in conflicts when a Python-script tries to import the path, being not unique anymore.

Here is an overview of the directory-structure and files involved, before we continue to explain their purposes in detail furtheron:

mynamespace.myaddon
    setup.py
    mynamespace
        __init__.py
        myaddon
            __init__.py
            myfile.py

To namespace an add-on firstly create a directory named ‘mynamespace.myaddon’.

This directory must contain the ‘setup.py’-file, it makes the egg registrable to the Python-interpreter of the ZOPE-instance, this is further explained in the next chapter[TODO].

Then, in that directory, create another directory named after your namespace: ‘mynamespace’ Now, we make this directory an importable module-path, by adding the keyword-named file __init__.py in it. It also must contain the following lines, which make the namespace-magic happen, explained in the last paragraph:

[TODO: namespace-magic-lines]

Phew almost done, lastly in this new directory we put the module of the previous chapter: The directory ‘myaddon’, containing the ’init.py’ and ‘myfile.py’ with the ‘myDefinition’.

Now we have an registrable egg for the ZOPE-instance and could reference its methods of any other registered egg, using this path-notation:

from mynamespace.myaddon.myfile import myDefinition

You might see the magic, the first two directories are omitted, it is not:

from mynamespace.myaddon.mynamespace.myaddon.myfile import myDefinition

Python-interpreter

[TODO:

  • Explain setup.py
  • Add a previous chapter about buildout (=installing Plone) for

reference. ]

Making an addon installable within a Plone-site

A ‘profile’ will make the add-on show up in the add-ons-controlpanel of a site, so an admin can (de-)activate it there for the site.

Additionally, as a Plone-site is always a child of ZOPE-instance and a ZOPE-instance can contain several sites, we might not want to have unintendendly components of our add-on installed in other Plone-sites, therefore we bind them to a ‘profile’.

TL;TR: devgen addProfile mynamespace.myaddon

This leads us to the really interesting parts, the ZOPE-Component-Architecture, controlled by the files ending with ‘.zcml’, which stands for ‘ZOPE-Component- Markup-Language’. With it you can register a profile, bind views to interfaces and much more. In fact, it deserves an own major chapter and a subchapter for each of the directories called “profile”, “skins”, “browser” and “content”.


This modified text is an extract of the original Stack Overflow Documentation created by the contributors and released under CC BY-SA 3.0 This website is not affiliated with Stack Overflow