Grok Developer's Notes
======================

This document is a developer's overview of Grok. It is not intended to
be a beginner's tutorial. It's also not a reference. It gives a
succinct an overview of *what's there* in Grok, with a brief idea on
how to use it, so you can try it out and learn more about it. This
includes rules, common APIs and patterns.

Models
------

A Grok-based application is composed out of one or more *models*. We
also call these *content objects*, or just *objects*. The objects are
just Python objects, instantiated from a class. Models can be stored
in the object database (ZODB), created by an object relational mapper,
or created on the fly by your code.

Grok comes with two kinds of models: ``grok.Model`` and
``grok.Container``. ``grok.Model`` is the most basic one and doesn't
really do much for you. You can subclass from ``grok.Model``, like
this::

  class Document(grok.Model):
      pass

The main thing subclassing from ``grok.Model`` does is make it
possible (but not required) to store instances in the ZODB.

You can also subclass from ``grok.Container``, like this::

  class Folder(grok.Container):
      pass

A container is like a model, but also acts much like a Python
dictionary. The main difference with Python dictionaries is that its
methods, like ``keys`` and ``items``, are iterator-like. They also do
more, like send events, but we can forget about that for now.

In order to be able to install an application, you need to mix in
``grok.Application`` into a class::

  class Application(grok.Application, grok.Container):
      pass

Instances of this class can now be installable in the Grok web UI.

Let's make a structure with some folders and documents::

  app = Application()
  app['a'] = a = Container()
  a['b'] = Document()
  a['c'] = Container()
  a['c']['d'] = Document()

Grok publishes these objects to the web: this is called object
publishing. What this means in essence is that objects can be
addressed with URLs. When you access a URL of a Grok application with
your web browser, Grok uses this URL to find an object.

An example: if ``app`` were installed under
``http://localhost:8080/app``, the following URLs will exist in your
application::

  http://localhost:8080/app
  http://localhost:8080/app/a
  http://localhost:8080/app/a/b
  http://localhost:8080/app/a/c
  http://localhost:8080/app/a/c/d

``__parent__`` and ``__name__``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Models in Grok are automatically supplied with a ``__parent__`` and a
``__name__`` attribute.

* ``__parent__`` points to object this object is in. If the object is in
  a container, this is the container.

* ``__name__`` is the name this object has in a URL (and in its
  container, if it is in a container).

These attributes are used for navigation through content space, and
Grok also uses them to construct URLs automatically (see below). The
``__parent__`` and ``__name__`` attributes are automatically added to
an object when it is placed in a container, or when it is being
traversed through using ``traverse``.

Custom traversing
~~~~~~~~~~~~~~~~~

Grok resolves URLs to objects by *traversing* through the containers
and models in question. What if you want to customize the way this
traversal works? Perhaps you want to traverse through objects you
create yourself, or objects created by an object relational
mapper. Grok offers a handy way to do so: the ``traverse`` method on
models.

A math example: imagine you want to create an application that
represents integer numbers, and you want to traverse to each
individual number, like this::

  http://localhost:8080/integers/0
  http://localhost:8080/integers/1
  http://localhost:8080/integers/2
  http://localhost:8080/integers/3
  ...

and so on. How would we implement this? We cannot create a container
and fill it with all integers possible, as there are an infinite
number of them. Okay, so we are in a math example, so let's be exact:
this is true if we ignore memory limitations and URL length
limitations. Storing all possible integers in a container is just not
*practical*.

We use the ``traverse`` method::

  class ParticularInteger(grok.Model):
      def __init__(self, number):
          self.number = number

  class Integers(grok.Application, grok.Model):
      def traverse(self, name):
          try:
               value = int(name)
          except ValueError:
               return None # not an integer
          return ParticularInteger(value)

Now all URLs for numbers are available. What's more, other URLs like
this are not::

  http://localhost:8080/integers/foo

The ``traverse`` method works by trying to convert the path element
that comes in as ``name`` to an integer. If it fails, we return
``None``, telling Grok that the ``traverse()`` method didn't find the
object asked for. Grok then falls back on default behavior, which in
this case would mean a ``404 Not Found`` error.

Traversable attributes
~~~~~~~~~~~~~~~~~~~~~~

In some cases, you want to traverse to attributes or methods of your
``grok.Model``. This can be done easily using the ``grok.traversable``
directive::

  class Mammoth(grok.Model):
      grok.traversable('trunk')

      trunk = Trunk()

  class MammothView(grok.View):
      grok.context(Mammoth)

      def render(self):
          return "I'm a mammoth!"

Now, if traversing to http://localhost/mammoth/trunk , a Trunk()
object will be exposed at that URL.

Views
-----

Now that we have models and can build structures of them, we will need
to look at ways to actually present them to the user: views. So what
is a view? A view is a class that represents a model in some way. It
creates a user interface of some sort (typically HTML) for a model. A
single model can have more than one view. It looks like this::

  class Index(grok.View):
      grok.context(Application)

      def render(self):
          return "This is the application"

The ``grok.context`` bit in the class is an example of using a *Grok
directive*. If you use ``grok.context`` on a view class, it connects
the view to the class we give it. So in this case, ``Index`` is a view
for ``Application``. Note that if there is only a single model in the
module and you want your view to be associated with it, you can leave
out ``grok.context`` and the view will be associated with that model
by default. Many directives have such default behavior, allowing you
to leave them out of your code if you organize your code in a certain
way.

The default view for a model is called ``index``. You can specify
``index`` at the end of the URL, like this::

  http://localhost:8080/app/index

What happens when you go to this URL is that Grok instantiates the
``Index`` class, creating a ``Index`` instance. View instances have
a number of attributes by default:

  * ``context``, the model instance that the view is presenting.

  * ``request``, the current web request.

  * ``response``, an object representing the response sent to the
                  user.  Used less often.

``index`` views are special, as it's also fine not to add ``index`` at
the end, because the name ``index`` is the default::

  http://localhost:8080/app

You can also create views with different names::

  class Edit(grok.View):
      grok.context(Application)

      def render(self):
          return "This is the edit screen for the application"

Now you can go to this URL::

   http://localhost:8080/app/edit

The name of the view is the name of the view class, lowercased. This
is the default behavior: you can override this using the ``grok.name``
directive::

  class SomeImpossiblyLongClassName(grok.View):
      grok.context(Application)
      grok.name('edit')

      def render(self):
          return "This is the edit screen for the application"

Templates
~~~~~~~~~

In the previous examples, we used the ``render`` method to determine
what you actually see on a web page. For most views we don't want to
do that: we want to use a template to prepare presentation. Using a
template with a view is easy.  First create a directory
``<name>_templates``, where ``<name>`` is the the module that contains
the views. So, if you are developing in a module ``app.py``, you need
to create a subdirectory ``app_templates`` for templates in the same
directory as the ``app.py`` module.

You can then add templates to that directory with the same name as the
view class name (lowercase), with the ``.pt`` extension
appended. These templates follow the Zope Page Template (ZPT) rules,
though Grok can also be extended to support other template languages.

You could for instance have this view::

  class Index(grok.View):
      grok.context(Application)

and a file ``index.pt`` in the module's templates directory containing
template code.

These are the defaults. If for some reason you want the name of the
template directory not to be based on the name of module, you can
manually set the name of the template directory used by a module by
using the ``grok.templatedir`` directive in the module. If you want
the name of the template not to be based on the name of the class, you
use the ``grok.template`` directive in the view class.

The template can access attributes and methods on the view through the
special ``view`` name available in the template. The template can
access attributes and methods on the model through the special
``context`` name available in the template. The template has the
following special names available::

* ``view`` - the view that this template is associated with

* ``context`` - the model that is being viewed

* ``request`` - the current request object

* ``static`` - to make URLs to static content made available by this module

and any names you also make available using the ``namespace`` method.

static content
~~~~~~~~~~~~~~

A typical web page references one or more CSS files, javascript files
and images: static content that is part of the layout.

To make available static content to your template create a directory
in your package called ``static``. Put ``.css`` files, ``.js`` files,
image and whatever else is needed in there.

You can now refer to these static files in your template using the
special name ``static``, like this (ZPT example)::

  <img tal:attributes="src static/my_image.png" />

This will automatically create a URL to the place where Grok published
that image.

You can create subdirectories in ``static`` and refer to them as you'd
expect::

  <image tal:attributes="src static/images/some_image.gif" />

``update``
~~~~~~~~~~

You can define an ``update`` method in a view to prepare a view just
before it is accessed. You can use this to process information in the
request (URL parameters or form variables) or in the context, and set
attributes on the view that can be used in the template::

  def update(self):
      self.total = int(self.request.form['a']) + int(self.request.form['b'])

The template now has access to ``view.total``.

You can define parameters in the update view. These will be
automatically bound to parameters (or form values) in the request::

  def update(self, a, b):
      self.total = int(a) + int(b)

``namespace``
~~~~~~~~~~~~~

If you just want a variable to become available in the top-level of
your template (much like ``view`` and ``model``), you can also define
the ``namespace`` method on the view::

  def namespace(self):
      return {'foo': "Some value"}

You can now refer to ``foo`` in your template and have available to
this value.

the ``url`` method
~~~~~~~~~~~~~~~~~~

Views have a special method called ``url()`` that can be used to
create URLs to objects. The ``url`` method takes zero, one or two
arguments and an additional optional keyword argument 'data' that
is converted into a CGI query string appended to the URL::

* self.url() - URL to this view.

* self.url(object) - URL to the provided object.

* self.url(u"name") - URL to the context object, with ``/name`` appended,
                   to point to a view or subobject of the context.

* self.url(object, u"name") - URL to the provided object, with
  		   ``/name`` appended, to point to a view or subobject
  		   of the provided object.

* self.url(object, u"name", data={'name':'Peter', 'age':28})
            - URL to the provided object, with ``/name`` appended
              with '?name=Peter&age=28' at the end.

* self.url(data={'name':u'Andr\xe9', 'age:int':28}) - URL to the provided
                   object with '?name=Andre%C3%A9'&age%3Aint=28'.

From the view, this is accessed through ``self.url()``. From the
template, this method can be accessed using ``view.url()``.

the ``application_url`` method
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When using views it is sometimes desirable to be able to construct a
URL to the application object. ``application_url`` is a quick way to
do it.  It takes a single optional argument, name, which is the name
of a view of the application.

the ``redirect`` method
~~~~~~~~~~~~~~~~~~~~~~~

The ``redirect`` method on views can be used to redirect the browser
to another URL. Example::

   def render(self):
       self.redirect(self.url(self.context.__parent__))
       # return empty body as we are going to redirect anyway
       return ''

``__parent__`` and ``__name__`` on views
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Like models, views also get supplied with a ``__parent__`` and
``__name__`` object when they are instantiated for a particular model.

``__parent__`` points to the model being viewed (and is the same as
``context``, which should normally be used).

``__name__`` is the name of the view in the URL.

The ``@@`` thing
~~~~~~~~~~~~~~~~

Supposing you have a view called ``edit``, whenever you write this::

  http://localhost:8080/app/edit

you can also write this::

  http://localhost:8080/app/@@edit

Why the ugly ``@@`` syntax? Imagine that ``app`` is a container, and
that your user interface lets the user add objects to it with a name
of their own choosing. The user could decide to add an object called
``index``. In that case Grok wouldn't know whether the
``http://localhost:8080/app/index`` index is to get to a view or a
subobject. ``@@`` tells the system to look up a view definitely. If
``@@`` is not provided, subobjects take precedence over views in case
of name collision.

Request
-------

Some useful things to know about the request object (accessible as an
attribute on the view):

Information on the ``request`` object can be accessed using mapping
access (``request[`foo`]``). You can access request form variables and
cookies and headers (including `environment variables`_).

.. _`environment variables`: http://hoohoo.ncsa.uiuc.edu/cgi/env.html

To access form variables in particular use: ``request.form['foo']``.

To access cookies in particular use: ``request.cookies['foo']``.

To access headers (and environment variables) in particular use:
``request.headers['foo']``. You can also use ``request.getHeader()``,
with the header name as the argument, and an optional second default
argument.

Instead of the mapping access, the ``get`` methods work as well, as on
normal Python dictionaries.

More can be found in the ``IHTTPRequest`` interface documentation
in ``zope.publisher.interfaces.http``.

Response
--------

Some useful things to know about the response object (accessible as
an attribute on the view):

``setStatus(name, reason)`` sets the HTTP status code. The argument
may either be an integer representing the status code (such as ``200``
or ``400``), or a string (``OK``, ``NotFound``). The optional second
argument can be be used to pass the human-readable representation
(``Not Found``).

``setHeader(name, value)`` can be used to set HTTP response headers. The first
argument is the header name, the second the value.

``addHeader(name, value)`` can be used to add a HTTP header, while
retaining any previously set headers with the same name.

``setCookie(name, value, **kw)`` can be used to set a cookie. The first
argument is the cookie name, the second the value. Optional keyword
arguments can be used to set up further cookie properties (such as
``max_age`` and ``expires``).

``expireCookie(name, value)`` can be used to immediately expire a
cookie.

More can be found in the ``IHTTPResponse`` interface documentation
in ``zope.publisher.interfaces.http``.

Adapters
--------

An adapter is much like a view, but is aimed towards developers, not
end users. It presents an interface to an object, but an interface for
developers, not an user interface for end-users.

The section on adapters will of necessity be rather abstract. Feel
free to skip it until you want to know what is going on up with
interfaces and adapters - it is an important foundation to Grok, but one
you do not know much about when you get started.

An adapter can be used to add new methods to an object without
changing the object. To demonstrate the principle, we will construct
adapters entirely by hand first. At the end we will show how Groks
helps in constructing adapters and using them.

Imagine we are developing a content management system and we want to
get information about the size (in, say, bytes, approximately) of
content objects stored in our CMS, for instance in order to display it
in our UI or to calculate the total size of all objects in a
container. The simplest approach would be to add a ``size()`` method
to all our content objects::

  class Document(grok.Model):
       def __init__(self, text):
           self.text = text

       def size(self):
           return len(self.text.encode('UTF-8'))

  class Image(grok.Model):
       def __init__(self, data):
            self.data = data

       def size(self):
            return len(self.data)

  class Container(grok.Container):
        def size(self):
            total = 0
            for obj in self.values():
                total += obj.size()
            return total

For simple cases this is fine, but for larger applications this can
become a problem. Our ``Document`` model needs a ``size`` method, and
does our ``Image`` model, and our ``Container``, and our ``News Item``
model, and so on. Given the requirements of a typical CMS, content
objects would soon end up with a very large number of methods, for all
sorts of functionality, from getting the size of objects to offering a
commenting facility. It would be nicer to separate things out and keep
the underlying models clean.

To do this, we can use the adaptation pattern. As said, we will do it
by hand at first. An adapter is an object that adds an API to another
object (typically stored as the ``context`` attribute of the
adapter)::

  class DocumentSized(object):
      def __init__(self, context):
          self.context = context

      def size(self):
          return len(self.context.text.encode('UTF-8'))

We would use it like this::

   DocumentSized(document).size()

We could extend this same adapter to work for different kinds of
content objects, but that isn't very extensible when new adapters need
to be made::

  class Sized(object):
      def __init__(self, context):
          self.context = context

      def size(self):
          if isinstance(self.context, Document):
               return len(self.context.text.encode('UTF-8'))
          elif isinstance(self.context, Image):
               return len(self.context.data)
          elif isintance(self.context, Container):
               total = 0
               for obj in self.context.values():
                   total += Sized(obj).size()
               return total

Instead, we can create a smart ``sized`` factory that does this
switch-on-type behavior instead, keeping our adapters clean::

  class DocumentSized(object):
      def __init__(self, context):
          self.context = context

      def size(self):
          return len(self.context.text.encode('UTF-8'))

  class ImageSized(object):
      def __init__(self, context):
          self.context = context

      def size(self):
          return len(self.context.data)

  class ContainerSized(object):
      def __init__(self, context):
          self.context = context

      def size(self):
          total = 0
          for obj in self.context.values():
              total += sized(obj).size()
          return total

  def sized(context):
      if isinstance(context, Document):
          return DocumentedSized(context)
      elif isinstance(context, Image):
          return ImageSized(context)
      elif isinstance(context, Container):
          return ContainerSized(context)

We can now call ``sized`` for a content object and get an object back
that implements the "sized API"::

   s = sized(my_content_object)
   print s.size()

It's good to spell out the APIs of your application explicitly, as
documentation so that other developers can work with them and also
implement them for their own content objects. Grok lets you do this
using an *interface* specification, using the ``zope.interface``
package::

  from zope.interface import Interface

  class ISized(Interface):
      def size():
           "Return the size of the object"

We can now make this ``ISized`` interface into the adapter factory
(like ``sized`` above), without actually having to implement it
directly. Let's do that now by subclassing from ``grok.Adapter`` and
using a few grok directives::

  class DocumentSized(grok.Adapter):
      grok.context(Document)
      grok.provides(ISized)

      def size(self):
          return len(self.context.text.encode('UTF-8'))

  class ImageSized(grok.Adapter):
      grok.context(Image)
      grok.provides(ISized)

      def size(self):
          return len(self.context.data)

  class ContainerSized(grok.Adapter):
      grok.context(Container)
      grok.provides(ISized)

      def size(self):
          total = 0
          for obj in self.context.values():
              total += ISized(obj).size()
          return total

We can now use ``ISized`` like we used ``sized`` above::

   s = ISized(my_content_object)
   print s.size()

When new content objects were to be created for this CMS, ``ISized``
adapters can be registered for them anywhere. Using this pattern,
existing objects implemented by someone else can be made to conform
with the ``ISized`` API without having to modify them.

``grok.context`` works as for views. It is useful to point it to any
class however, not just that of models. ``grok.provides`` has to be
pointed to an interface (the interface that the adapter *adapts to*).

Interfaces
~~~~~~~~~~

Classes can also be made to *implement* an interface. This means that
instances of that class *provide* that interface::

  from zope.interface import Interface, Attribute

  class IAnimal(Interface):
      name = Attribute("The name of the animal")

      def makeSound():
          "The sound the animal makes."

  class Cow(object):
      grok.implements(IAnimal)

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

      def makeSound(self):
          return "Mooo"

We can ask the interface machinery whether an object provides an interface::

  >>> cow = Cow()
  >>> IAnimal.providedBy(cow)
  True

If you use an interface to adapt an object, and this object already
provides the interface, you get back the object itself::

  >>> IAnimal(cow) is cow
  True

``grok.context`` can always point to an interface instead of a class
directly. This indirection can be useful to make a view or adapter
work for a whole set of classes that all implement the same interface.

``ComponentLookupError``
~~~~~~~~~~~~~~~~~~~~~~~~

What if an adapter cannot be found for a particular object? Perhaps no
adapter has been registered for a particular object or a particular
interface. The system will raise a ``ComponentLookupError``::

  >>> ISized(cow)
  Traceback (most recent call last):
    ...
  ComponentLookupError

If you want to catch this exception, you can import it from
``zope.component.interfaces``::

  from zope.component.interfaces import ComponentLookupError

Named adapters
~~~~~~~~~~~~~~

It is possible to give an adapter a name, making it a *named
adapter*. This way it is possible to have more than one adapter
registered for a single object that all provide the same interface,
each with a different name. This feature is rarely used directly,
but internally it is used for views, as we will see later. The
``grok.name()`` directive can be used to give an adapter a name::

  class Adapter(object):
      grok.name('somename')
      grok.context(SomeClass)
      grok.provides(ISomeInterface)

Actually all adapters are named: by default the name of an adapter is
the empty string.

You cannot call the interface directly to get a named adapter for an
object.  Instead, you need to use the APIs provided by the
``zope.component`` package, in particular ``getAdapter``::

  from zope import component

  my_adapter = component.getAdapter(some_object, ISomeInterface,
                                   name='somename')

``getAdapter`` can also be used to look up unnamed adapters, as an
alternative to using the interface directly::

  myadapter = component.getAdapter(some_object, ISomeInterface)

Functions as adapters
~~~~~~~~~~~~~~~~~~~~~

Sometimes an adapter doesn't need to be a full-fledged class;
registering the factory function itself is enough. We can do this with
the ``@grok.adapter`` and ``@grok.implementer`` decorators. This way
we can write simple adapters that don't need to return a full-fledged
custom class instance but for instance some built-in Python object
like a string::

  @grok.adapter(SomeClass)
  @grok.implementer(ISomeInterface)
  def some_interface_for_some_class(some_instance):
      return str(some_instance)

You can now do the following::

  some_instance = SomeClass()
  s = ISomeInterface(some_instance)
  print s

``ISomeInterface`` now behaves much like ``str`` for ``SomeClass``.

Multi adapters
~~~~~~~~~~~~~~

Another feature of adapters is that you can adapt multiple objects at
once using a *multi adapter*. Again this feature is rarely used in
practice, except internally to implement views and events.

You can construct a multi adapter by subclassing from
``grok.MultiAdapter``::

  class MyMultiAdapter(grok.MultiAdapter):
      grok.adapts(SomeClass, AnotherClass)
      grok.provides(ISomeInterface)

      def __init__(some_instance, another_instance):
          self.some_interface = some_instance
          self.another_instance = another_instance

The multi-adapter receives as many arguments as what it was registered
for using ``grok.adapts``.

A multi adapter also cannot be looked up directly by calling the
interface. Instead, we need to use the ``zope.component`` package
again::

  from zope import component

  my_multi_adapter = component.getMultiAdapter((some_object, another_object),
                                               ISomeInterface)

``getMultiAdapter`` receives as the first argument a tuple with the
combination of objects to adapt.

It can also optionally be named using ``grok.name`` and then looked up
using a name argument::

  my_named_multi_adapter = component.getMultiAdapter(
      (some_object, another_object), ISomeInterface, name="foo")

Views as adapters
~~~~~~~~~~~~~~~~~

A view in Grok is in fact a named multi adapter, providing the base
interface (``Interface``). This means that a view in Grok can be
looked up in code by the following call::

  from zope.interface import Interface

  view = component.getMultiAdapter((object, request), Interface, name="index")

Since the default for the second argument is in fact ``Interface``, this
call can be shorted to this::

  view = component.getMultiAdapter((object, request), name="index")

Being able to do this in code is sometimes useful. It is also what
Grok does internally when it looks up a view.

Events
------

Grok lets you write handlers for *events*. Using event handlers you
can hook into code that you do not control. Events allow decoupling: a
framework can send events without worrying who is interested in it,
and similarly you can send events to work with existing bits of
framework that expects them. You can also define new types of events
if you are designing a framework yourself.

You write an event handler by writing a function that *subscribes* to
the event, and marking it with a python decorator::

  @grok.subscribe(Document, grok.IObjectAddedEvent)
  def handle(obj, event):
      print "Object %s was added." % obj

Whenever an instance of a model of class ``Document`` (or subclasses)
is added to a container, this code will be run. You can then take some
action. Any ``grok.Container`` subclass will take care of sending
these events automatically.  You can have as many subscribers for a
particular event as you like.  The order in which they are run is not
guaranteed by the system, so cannot be relied on.

The event handler takes two arguments: the object for which the event
was fired, and the event instance. The event instance has attributes,
depending on the type of event.

Events defined by Grok
~~~~~~~~~~~~~~~~~~~~~~

Here we describe the standard events defined by Grok. Described are
the interfaces which you would use in a subscriber, and how you can
send this event yourself. Other events may be defined by libraries or
by you.

``IObjectMovedEvent``
+++++++++++++++++++++

Will be fired whenever an object is moved from container to container,
renamed, added or removed.

The event object has these attributes:

* ``object`` - the object being moved

* ``oldParent`` - the parent (container) from which the object was moved
                  or removed, or ``None`` if this object is newly added.

* ``oldName`` - the previous name of the object in its container,
                before renaming if renaming took place, or ``None`` if
                this object is newly added.

* ``newParent`` - the parent (container) to this object was moved or
                added. ``None`` if this object was removed.

* ``newName`` - the name the object has in the new container, or ``None``
                if this object was removed.

Containers take care of sending this event, but should you want to
send it yourself, use::

  grok.notify(grok.ObjectMovedEvent(obj, oldParent, oldName, newParent, newName))

``IObjectAddedEvent``
+++++++++++++++++++++

Fired when an object is added to a container. Specialization of
``IObjectMovedEvent``, and shares the attributes as described.

Containers take care of sending this event, but should you want to send it
yourself, use::

  grok.notify(grok.ObjectAddedEvent(obj))

or::

  grok.notify(grok.ObjectAddedEvent(obj, newParent, newName))

``IObjectRemovedEvent``
+++++++++++++++++++++++

Fired when an object is removed from a container (and not re-added
elsewhere). Specialization of ``IObjectMovedEvent``, and shares the
attributes as described.

Containers take care of sending this event, but should you want to send it
yourself, use::

  grok.notify(grok.ObjectRemovedEvent(obj)

or::

  grok.notify(grok.ObjectRemovedEvent(obj, oldparent, oldName))

``IObjectModifiedEvent``
++++++++++++++++++++++++

Fired when an object is modified by the system, such as when a form is
saved. If you modify the object in code, the system won't know about
this, and you will have to remember to send it yourself.

This event has a single attribute, ``object``, which is the object
that was modified.

To send this event yourself, use::

  grok.notify(grok.ObjectModifiedEvent(obj))

``IContainerModifiedEvent``
+++++++++++++++++++++++++++

A specialization of ``IObjectModifiedEvent`` that fires when the
container was modified by adding something to it or removing from it.

Containers take care of sending this event, but if you want to send it
yourself, use::

  grok.notify(grok.ContainerModifiedEvent(obj))

``IObjectCreatedEvent``
+++++++++++++++++++++++

Fired when an object is created. When you create your own objects the
system won't know about this, and you will have to remember to send it
yourself if you care about listing to ``IObjectCreatedEvent``. This is
fairly rare - usually you're better of looking at
``IObjectAddedEvent`` if you can.

This event has a single attribute, ``object``, which is the object
that was created.

To send this event yourself::

  grok.notify(grok.ObjectCreatedEvent(obj))

``IObjectCopiedEvent``
++++++++++++++++++++++

Fired when an object was copied. It is a specialization of
``IObjectCreatedEvent`` that is fired by the system if you use the
``zope.copypastemove`` functionality.

Besides the ``object`` attribute it shares with
``IObjectCreattedEvent``, it has also has the ``original`` attribute,
which was the object that iwas copied from.

To send this event yourself::

  grok.notify(grok.ObjectCopiedEvent(copy, original))

``IBeforeTraverseEvent``
+++++++++++++++++++++++++

Fired when the publisher is about to traverse into your object. This
is useful to specify on your application object if you for instance
want to set the default skin for your application.

Creating and sending your own events
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

If you are going to send an object that pertains to a particular object,
subclass ``zope.component.interfaces.ObjectEvent``::

  from zope.component.interfaces import ObjectEvent

  class MyEvent(ObjectEvent):
      pass

You can then send it like this::

  grok.notify(MyEvent(some_obj))

And listen for it like this::

  @grok.subscribe(SomeClass, MyEvent)
  def handle_my_event(obj, event):
      pass

This subclassing from ``ObjectEvent`` is not required; if your event
isn't about an object, you can choose to design your event class
entirely yourself. See ``zope.sendmail`` for the construction of mail sending
events for an example.

Interfaces for events
~~~~~~~~~~~~~~~~~~~~~

For documentation purposes it can be a good idea to to define an
interface for your event. You can then also allow for multiple
implementations of the same event interface. When you have an
interface for your event, you can then listen for the interface in the
subscribers as well::

  from zope.interface import Interface

  class IMyEvent(zope.component.interfaces.IObjectEvent):
      "My special event"

  class MyEvent(zope.component.interfaces.ObjectEvent):
      grok.implements(IMyEvent)

  @grok.subscribe(SomeClass, IMyEvent):
  def handle_my_event(obj, event):
      pass

More about interfaces
---------------------

We have seen small examples of interfaces before, but here we will go
a bit more into them, and why they are useful.

An *interface* is a description of the API of a class (or more rarely,
module or object). Interfaces are useful because:

* They are API documentation.

* They can describe how a framework expects you to implement classes
  that fit into it.

* The system can inspect the interfaces a particular object provides,
  and treat them as an abstract form of classes for registration
  purposes.

Interfaces make it possible to use a generic framework's pluggability
points with confidence: you can clearly see what you are supposed to
implement to plug into it. You can define very generic frameworks
yourself by defining them in terms of interfaces.

Some interface features
~~~~~~~~~~~~~~~~~~~~~~~

A summary of interface features we've seen:

* To create an interface, subclass from ``zope.interface.Interface``.

* To state that implementors of the interface must have a method, supply
  the method with arguments. Don't use ``self`` as the first
  arguments, as this is an implementation detail not important to the
  interface. Instead, describe the methods as they look to the caller.

* To state that implementors of the interface must have an attribute, use::

    some_attribute = zope.interface.Attribute("Description of attribute")

* To state a class *implements* an interface, use ``grok.implements``.

* Instances of a class are said to *provide* the interface that the
  class *implements*.

* You can check whether an instance provides a certain interface by using
  ``some_interface.providedBy``::

     IObjectEvent.providedBy(NonSubclassEvent(some_obj))

Interfaces and events
~~~~~~~~~~~~~~~~~~~~~

Let's study interfaces some more in connection with
``IObjectModifiedEvent``. The ``IObjectModifiedEvent`` interface looks
like this::

  class IObjectModifiedEvent(zope.component.interfaces.IObjectEvent):
      """An object has been modified"""

This refers us to the ``IObjectEvent`` interface, which looks like
this::

  from zope import interface

  class IObjectEvent(interface.Interface):
      """An event related to an object.
      """

      object = interface.Attribute("The subject of the event.")

We therefore know that if we implement ``IObjectModifiedEvent``, we
must supply a single attribute, ``object``.

The following event handler for instances of ``SomeClass`` subscribes
to *any* event that provides ``IModifiedObjectEvent``::

   @grok.subscribe(SomeClass, IObjectModifiedEvent):
   def handle_event(obj, event):
       "Called when there is an IObjectModifiedEvent for SomeClass instances."

This handler will be called not only for subclasses of the
``grok.ObjectModifiedEvent`` class, but also for other, otherwise
unrelated classes that implement ``IObjectEvent``, such as this one::

  class NonSubclassObjectEvent(object):
      grok.implements(IObjectEvent)

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

So far we have only used interfaces for the second argument of the
event handler registration, but the principle also works for the first
argument. For example, to handle ``IObjectModifiedEvent`` events for
all kinds of containers, you can subscribe to
``zope.app.container.interfaces.IContainer`` objects::

  @grok.subscribe(IContainer, IObjectModifiedEvent):
  def handle_event(obj, event):
      "Called whenever any container is modified"

``zope.app.container.interfaces.IContainer`` defines the abstract
container API that all containers must provide, no matter how they are
implemented internally.

Interfaces and adapters
~~~~~~~~~~~~~~~~~~~~~~~

The same principle also works for adapters and ``grok.context``. You
can use ``grok.context`` with interfaces as well as with concrete
classes. To write an adapter that works for any kind of container, you
can write::

  from zope.app.container.interfaces import IContainer

  class SortedKeysAdapter(grok.Adapter):
      grok.context(IContainer)
      grok.provides(ISortedKeys)

      def sortedKeys(self):
          return sorted(self.context.keys())

Interfaces and views
~~~~~~~~~~~~~~~~~~~~

The same principle can also be used with ``grok.context`` in other
places, such as in views. This view is registered for all containers::

  from zope.app.container.interfaces import IContainer

  class Keys(grok.View):
     grok.context(IContainer)

     def render(self):
         return ', '.join(ISortedKeysAdapter(self.context).sortedKeys())

The view ``keys`` exists for all containers, no matter how they are
implement, where they are implemented or who implemented them, as long
as they provide ``IContainer``.

Using the fact ``Interface`` is the base of all interfaces, you can
even register a view for *all* objects. This can be useful to register
ZPT macros, which will then be available on all contexts::

  class Layout(grok.View):
      grok.context(Interface)

with a template ``layout.pt`` associated to it.

You can then use these macros in any page template anywhere by
referring to them like this::

  <html metal:use-macro="context/@@layout/macros/page">

Forms
-----

Grok can autogenerate web forms from descriptions called *schema*. A
schema is a special kind of interface. We already saw ``Attribute``,
which can be used to specify that something that provides that
interface should have that attribute. The ``zope.schema`` package adds
a lot more specific field descriptions. Here is an example of a
schema::

  from zope.interface import Interface
  from zope import schema

  class ISpecies(Interface):
      name = schema.TextLine(u"Animal species name")
      scientific_name = schema.TextLine(u"Scientific name")
      legs = schema.Int(u"Number of legs")

Let's also look at a simple implementation of this interface::

  class Species(grok.Model):
      grok.implements(ISpecies)

Note how we aren't even creating an ``__init__`` to set the
attributes; we could, but we'll see below that Grok's ``applyData``
can take care of this automatically.

The ``ISpecies`` schema can be turned into a form. Grok does this by
looking up a *widget* for each schema field to display it. A widget is
very much like a view. Let's look at a form for this schema::

  class Species(grok.Form):
      form_fields = grok.Fields(ISpecies)

      @grok.action(u"Save form")
      def handle_save(self, **data):
          print data['name']
          print data['scientific_name']
          print data['legs']

What is going on here? Firstly we use a special base class called
``grok.Form``. A form is a special kind of ``grok.View``, and
associates the same way (using ``grok.context``). A form expects two
things:

* a ``form_fields`` attribute. Above we see the most common way to construct
  this attribute, using ``grok.Fields`` on the interface.

* one or more actions. Actions are specified by using the
  ``@grok.action`` decorator. An action gets the fields filled in the
  form as keyword parameters, so ``**data`` in this case. We could
  also have specified the arguments we expected specifically.

Form widgets translate the raw HTML form input to Python objects, such
as (unicode) strings, integers and datetime objects, as specified by
schema fields. The schema fields can then be used to validate this
input further. Forms are self-submitting, and in case of a validation
error the form can render them in-line next to the fields.

We'll look at a lot of form features next.

``grok.AddForm``
~~~~~~~~~~~~~~~~

An add form is used to create a new object. Most forms are views of
the object that they are representing, but an add form is typically
associated a view of the container in which new objects are to be
added. Let's look at an example::

  class SpeciesContainer(grok.Container):
      pass

  class Add(grok.AddForm):
      grok.context(SpeciesContainer)

      form_fields = grok.Fields(ISpecies)

      @grok.action(u"Add species")
      def add_species(self, **data):
          # create a species instance
          species = Species()
          # assign the right attributes to fulfill ISpecies schema with
          # the form data
          self.applyData(species, **data)
          # stores the instance into the SpeciesContainer
          name = data['name']
          self.context[name] = species
          # redirect to the newly created object
          self.redirect(self.url(species))
          # we don't want to display anything, as we redirect
          return ''

The user can now go to ``myspeciescontainer/add`` to add a species,
where ``myspeciescontainer`` is any instance of ``SpeciesContainer``.

``grok.EditForm``
~~~~~~~~~~~~~~~~~

Now that we can create species objects, let's create a form so you can
easily edit them. This *is* a view of the ``Species`` model::

  class Edit(grok.EditForm):
     grok.context(Species)

     form_fields = grok.Fields(ISpecies)

     @grok.action(u"Edit species")
     def edit_species(self, **data):
          self.applyData(species, **data)

Forms are self-submitting, so this will show the edit form again. If
you want to display another page, you can redirect the browser as we
showed for the add form previously.

The user can now go to ``myspecies/edit`` to edit the species.

``grok.DisplayForm``
~~~~~~~~~~~~~~~~~~~~

Sometimes you just want to display an object, and not actually edit
it. If the object is schema-based, an easy way to do this is to use
display forms. Let's look at an example::

  class Display(grok.DisplayForm):
     grok.context(Species)

     form_fields = grok.Fields(ISpecies)

The user can now go to ``myspecies/display`` to look at the species.

Associating a template for a form
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

By default, Grok supplies some templates for forms. They work, but
they are not very pretty and don't fit into your application's
layout. You can instead use your own form rendering logic in a
template you associate with the form just like you associate templates
with views. You can also abstract form rendering logic you keep
reusing into a ZPT macro. Below is an example of form rendering logic
to help you get started. The example doesn't have any consideration
for layouting to make the logic clear. As a result, the form will be
very ugly if you use this - you will want to use CSS or table HTML to
layout things::

  <!-- render the form tag -->
  <form action="." tal:attributes="action request/URL" method="post"
        class="edit-form" enctype="multipart/form-data">
    <!-- render any validation errors on top -->
    <ul class="errors" tal:condition="view/errors">
      <li tal:repeat="error view/error_views">
         <span tal:replace="structure error">Error Type</span>
      </li>
    </ul>

    <!-- render the widgets -->
    <tal:block repeat="widget view/widgets">
      <label tal:attributes="for widget/name">
        <!-- a * when the widget is required -->
        <span class="required" tal:condition="widget/required">*</span>
        <!-- the title of the field -->
        <span i18n:translate="" tal:content="widget/label">label</span>
      </label>

      <!-- render the HTML widget -->
      <div class="widget" tal:content="structure widget">
        <input type="text" />
      </div>

      <!-- render any field specific validation error from a previous
           form submit next to the field -->
      <div class="error" tal:condition="widget/error">
        <span tal:replace="structure widget/error">error</span>
      </div>
    </tal:block>

    <!-- render all the action submit buttons -->
    <span class="actionButtons" tal:condition="view/availableActions">
      <input tal:repeat="action view/actions"
             tal:replace="structure action/render" />
    </span>
  </form>

The template for a display form a lot simpler::

  <tal:block repeat="widget view/widgets">
    <tal:block content="widget/label" />
    <input tal:replace="structure widget" />
  </tal:block>

  <!-- render all the action submit buttons -->
  <span class="actionButtons" tal:condition="view/availableActions">
    <input tal:repeat="action view/actions"
           tal:replace="structure action/render" />
  </span>
