Choosing a methodΒΆ

In this tutorial, we introduce four methods for creating an object which you need to present on the web:

  • Creating it in your View’s update(), using no external data.
  • Creating it in your View’s update(), using URL or form data.
  • Creating it in a Traverser that gets called for certain URLs.
  • Creating it in a Container that gets called for certain URLs.

To choose among these methods, the big question you need to ask yourself is whether the object you are planning to display is one that will live at its own particular URL or not. There are three basic relationships we can imagine between an object on a web page and the URL of the page itself.

The simplest case, which is supported by the first method listed above, is when you need to create an object during the rendering of a page that already exists in your application. An example would be decorating the bottom of your front page with a random quotation selected by instantiating a RandomQuotation class you have written, so that each time a user reloads the page they see a different quote. None of the quotations would thereby have URLs of their own; there would, in fact, be no way for the user to demand that a particular quotation be displayed; and the user could not force the site to display again a quote from Bertrand Russell that they remember enjoying yesterday but have forgotten. Such objects can simply be instantiated in the update() method of your View, and this technique will be our first example below.

The situation is only slightly more complex when you need to use form parameters the user has submitted to tailor the object you are creating. This is very common when supporting searching of a database: the user enters some search terms, and the application needs to instantiate an object β€” maybe a SearchResult or a DatabaseQuery β€” using those user-provided search terms, so that the page template can loop across and display the results. The second method listed above is best for this; since the form parameters are available in the update() method, you are free to use them when creating the result object. This will be the technique illustrated in our second example below.

Finally, the really interesting case is when an object actually gets its own URL. You are probably already familiar with several kinds of object which have their own URLs on the Web β€” such as books on Amazon.com, photographs on Flickr, and people on Facebook, all of which live at their own URL. Each web site has a particular scheme which associates a URL with the object it names or identifies. You can probably guess, for example, just by looking at them, which object is named by each of the following three Amazon URLs:

http://www.amazon.com/Web-Component-Development-Zope-3/dp/3540223592
http://www.amazon.com/Harry-Potter-Deathly-Hallows-Book/dp/0545010225
http://www.amazon.com/J-R-R-Tolkien-Boxed-Hobbit-Rings/dp/0345340426

The Grok framework, of course, already supports URL traversal for persistent objects in the ZODB; if you create a Container named polygons that contains two objects named triangle and square, then your Grok site will already support URLs like:

http://yoursite.com/app/polygons/triangle
http://yoursite.com/app/polygons/square

But the point of this tutorial, of course, is how you can support URL traversal for objects which are not persistent, which you will create on-the-fly once someone looks up their URL. And the answer is that, to support such objects, you will choose between the last two methods listed above: you will either create a custom Traverser, or actually define your own kind of Container, that knows how to find and instantiate the object the URL is naming. These two techniques are described last in this tutorial, because they involve the most code.

But before starting our first example, we need to define an object that we want to display. We want to avoid choosing an obvious example, like an object whose data is loaded from a database, because then this tutorial would have to teach database programming too! Plus, you would have to set up a database just to try the examples. Instead, we need an object rich enough to support interesting attributes and navigation, but simple enough that we will not have to reach outside of Python to instantiate it.