Having Your View Directly Instantiate An Object

We now reach the first of our four techniques!

The simplest way to create a transient object for display on the web involves a technique you may remember from the main Grok tutorial: providing an update() method on your View that creates the object you need and saves it as an attribute of the View. As a simple example, create an app.py file with these contents:

import grok
from transient.natural import Natural

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

class Index(grok.View):
    def update(self):
        self.num = Natural(126)

Do you see what will happen? Right before Grok renders your View to answer a web request, Grok will call its update() method, and your View will gain an attribute named num whose value is a new instance of the Natural class. This attribute can then be referenced from the page template corresponding to your view! Let use write a small page template that accesses the new object. Try creating an /app_templates/index.pt file that looks like:

<html><body>
 <p>
  Behold the number <b tal:content="view/num">x</b>!
  <span tal:condition="view/num/is_prime">It is prime.</span>
  <span tal:condition="view/num/is_composite">Its prime factors are:</span>
 </p>
 <ul tal:condition="view/num/factors">
  <li tal:repeat="factor view/num/factors">
   <b tal:content="factor">f</b>
  </li>
 </ul>
</body></html>

If you now run your instance and view the main page of your application, your browser should show you something like:

Behold the number 126! It has several prime factors:

  • 2
  • 3
  • 3
  • 7

You should remember, when creating an object through an update() method, that a new object gets created every time your page is viewed! This is hard to see with the above example, of course, because no matter how many times you hit “reload” on your web browser you will still see the same number. So adjust your app.py file so that it now looks like this:

import grok, random
from transient.natural import Natural

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

class Index(grok.View):
    def update(self):
        self.num = Natural(random.randint(1,1000))

Re-run your application and hit “reload” several times; each time you should see a different number.

The most important thing to realize when using this method is that this Natural object is not the object that Grok is wrapping with the View for display! The object actually selected by the URL in this example is your TransientApp application object itself; it is this application object which is the context of the View. The Natural object we are creating is nothing more than an incidental attribute of the View; it neither has its own URL, nor a View of its own to display it.