[[TOC(heading=Egg Cooking Tutorial, EggCookingTutorial/BasicEggCooking, EggCookingTutorial/AdvancedEggCooking, EggCookingTutorial/AdvancedEggCooking2, EggCookingTutorial/publish)]]
= Cook even better eggs
After you read [wiki:EggCookingTutorial/BasicEggCooking] and created your first egg, it's time to make it a bit better.
First we integrate our output to other Trac layout in form of !ClearSilver template.
== Adding template
To have a template we need a directory and of course the template itself. We will keep the same simple "Hello world!" text, but this time we will integrate our fine words into a Trac layout.
For that we need to create one additional directory:
{{{#!sh
./helloworld-plugin/helloworld/templates/
}}}
In that directory create a new file ''helloworld.html'':
{{{#!text/html
Hello world!
Hello world!
}}}
Now you have created the template for the plugin.
== Tell Trac where the template is
Trac doesn't know where your template is, so you have to tell it. This is done by implementing the ITemplateProvider interface in ''helloworld.py''.
So you change few lines as following:
Line 4 is changed from:
{{{#!python
from trac.web.chrome import INavigationContributor
}}}
to:
{{{#!python
from trac.web.chrome import INavigationContributor, ITemplateProvider
}}}
Line 9 is changed from:
{{{#!python
implements(INavigationContributor, IRequestHandler)
}}}
to:
{{{#!python
implements(INavigationContributor, IRequestHandler, ITemplateProvider)
}}}
Starting from line 23 old ''process_request'' method is replaced by:
{{{#!python
def process_request(self, req):
return 'helloworld.html', {}, None
}}}
And to end of file you need to tell where your template is located:
{{{#!python
# ITemplateProvider methods
def get_templates_dirs(self):
"""Return a list of directories containing the templates"""
from pkg_resources import resource_filename
return [resource_filename(__name__, 'templates')]
}}}
And the complete version of ''helloworld.py'' then becomes:
{{{#!python
# Helloworld plugin
from trac.core import *
from trac.util.html import html
from trac.web.chrome import INavigationContributor, ITemplateProvider
from trac.web.main import IRequestHandler
class HelloworldPlugin(Component):
implements(INavigationContributor, IRequestHandler, ITemplateProvider)
# INavigationContributor methods
def get_active_navigation_item(self, _):
return 'helloworld'
def get_navigation_items(self, req):
yield('mainnav', 'helloworld',
html.a('Hello', href=req.href.helloworld()))
# IRequestHandler methods
def match_request(self, req):
return req.path_info == '/helloworld'
def process_request(self, _):
return 'helloworld.html', {}, None
# ITemplateProvider methods
def get_templates_dirs(self):
""" provide template dir """
from pkg_resources import resource_filename
return [resource_filename(__name__, 'templates')]
}}}
== Copy template to egg
Finally you have to include the new template directory in an egg.
So change ''setup.py'' to be like:
{{{#!python
from setuptools import setup
PACKAGE = 'TracHelloworld'
VERSION = '0.1'
setup(name=PACKAGE,
version=VERSION,
packages=['helloworld'],
entry_points={'trac.plugins': '%s = helloworld' % PACKAGE},
package_data={'helloworld': ['templates/*.html']},
)
}}}
== Building and deploying
Building and deployment goes exactly the same as it did in the previous tutorial [wiki:EggCookingTutorial/BasicEggCooking#Firstdeployment EggCookingTutorial/BasicEggCooking].
Now you should see a big "Hello world!" integrated into your Trac layout when you press that fancy button in the main navigation bar.
== Aftermath
Now that you have added a basic template for your plugin let's add the final twist, putting some static content like a stylesheet and an image. Continue to [wiki:EggCookingTutorial/AdvancedEggCooking2].