Our application, being a wiki, consists of articles.  The way we would like to structure things, is for an article also to contain other articles.  Thus, when one is viewing one page, one should be able to navigate to any pages contained by the current one, or to the parent.  One should also be able to navigate back and forth through sibling pages- siblings are pages contained by the current article's parent.

By the above specification, we know that an article is a container (grok.Container). The application itself is also an article.  We define the interface for an article as follows:

class IArticle(Interface):
    title = TextLine(title=u'Page Title:', description=u'The title of the displayed page')
    navTitle = TextLine(title=u'Nav Title:', description=u'A title for the navigation area')
    text  = Text(title=u'Display Text:', description=u'Text to display on this page')

We can see that an article contains a title, a navigation title and text.  As previously discussed, the attributes are instances of schema field classes, which may be mapped to fields and widgets in automatically generated forms.

Now, we also know that articles will be containers, and that applies both to the application itself as well as any contained articles.  So it's a good idea to capture that fact in code:

class ArticleContainer(grok.Container):
    '''  An article container is a generic container (a dict-like object) which
        also provides a sorter for the articles it contains
    '''
    grok.traversable('attachments')
    grok.traversable('sorter')

    attachments = None
    def sorter(self):
        '''  Find an adapter which adapts self to an IArticleSorter, and return an instance
        '''
        return IArticleSorter(self)

We are already getting ahead of ourselves here with the definition of ArticleContainer.attachments; we shall discuss the IArticleSorter interface and adapter in due course.  In the above, we are saying that traversing to an 'article/sorter' will return an instance of an IArticleSorter

For the moment, what is contained in attachments is still unknown, but if we assume it to be a list of attachments, this would not be far from the truth.

As for our application and contained articles, the difference is that the application has no parent and is at the root of the site, where every other kind of article has a parent:

class NoobsArticle(ArticleContainer):
    ''' Contains the detail for a navigable article in the site
    '''
    grok.implements(IArticle, ILayout)
    title = u''
    navTitle = u''
    text = u''

class Grok4Noobs(grok.Application, ArticleContainer):
    ''' The Grok4Noobs application is a content wiki-like application which contains examples
        explaining how to use the Grok framework for trivial and non-trivial applications.
    '''
    grok.implements(IArticle, ILayout)
    title = u'A gentle introduction to using the Grok web framework'
    navTitle = u'Introduction'
    text = u''

We can see how both the Grok4Noobs application as well as the contained NoobsArticles are instances of ArticleContainer.  They also both implement IArticle and ILayout interfaces, thus inheriting the behaviour associated with those interfaces such as views, menus, viewlets and so forth.

As there is an index view defined for ILayout, our above classes also get the index view.  This view, as we have already discussed, will render providers (viewlet managers) for the various parts of the web page such as masthead, navigation or content. This means that we can easily include the article content by defining a viewlet manager for an IArticle:

class TextViewlet(grok.Viewlet):
    ''' Render the article content
    '''
    grok.context(IArticle)
    grok.viewletmanager(Content)

The template for TextViewlet will decide what should go into the Content slot when rendering an IArticle.

Grok 4 Noobs

Defining an Article and the Application