Basics
Let's create a small website with spg (download source). Please note that all the content will be made up and the result will be a very simple and stupid site. All the images are taken from sxc.hu.
Our file structure will be like following;
/index.html
/about.html
/contact.html
/main.css
/me.jpeg
/border.jpeg
/photography/index.html
/photography/nature.html
/photography/interior.html
/photography/images/green_wall.jpeg
/photography/images/meeting_room.jpeg
/photography/images/pikes_peak_mountain.jpeg
/photography/images/room_with_chair_and_desk.jpeg
/photography/images/waiting.jpeg
/photography/images/zingaro_reserve.jpeg
We will be covering only the emphasized files in this tutorial. But please go ahead and download the whole source now.
All the information spg needs to generate static files are written in template files. A template file consist of two parts; headers and template body. These two parts are seperated by 2 blank lines. Let us leave headers out and create a template with just a body.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"↵
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>%(TITLE)s</title>
</head>
<body>
%(CONTENT)s
</body>
</html>
Notice the two blank lines at the beginning. There must be a seperator when we don't have any headers.
Now we have a simple template containing only the necessary elements in a HTML page. Hopefully you have noticed the strange notation inside the title and body tags. These are mount points for our variables. Some other text will replace them depending on what we add to headers.
For example, just to get the silly tradition out of the way;
define TITLE "Hello"
define CONTENT "Hello world!"
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"↵
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>%(TITLE)s</title>
</head>
<body>
%(CONTENT)s
</body>
</html>
Here we have defined two constants to be used in our template body. If we render our page with spg we get something like this;
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"↵
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Hello</title>
</head>
<body>
Hello world!
</body>
</html>
I know, nothing fancy. Just the basic string interpolation if you know about Python. But spg, being a simple tool, also allows you to perform complicated abtractions with your code. In a simple way of course. Let's continue with more advanced concepts...
Parenting
Perhaps the most important feature of spg is that it allows arbitrary levels of parenting. You can seperate the repeating parts and unique (to a page) parts of your code. When the child (unique part) is rendered it inserts itself into the parent (repeating) template. So then when you change the parent only and all the children will be rendered correctly next time.
Let us take a slightly different version of our previous template;
define MY_NAME "Bruno Gondolsk"
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"↵
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" href="/main.css" type="text/css" />
<title>%(MY_NAME)s's Exceptionally Good↵
Photography%(TITLE)s</title>
</head>
<body>
%(BODY)s
</body>
</html>
Here we have defined a constant named MY_NAME. Isn't it pointless! Why don't we just write it there instead of %(MY_NAME)s? It is because we will make this a parent template for all our pages and use MY_NAME constant in some other places. (Yes, substituting a 14 character string with an 11 character long one isn't much practical. But in a real example this content can be much longer and more importantly, unlike a name, it can ben something that might change in time.)
In the template body we have two mount points (TITLE and BODY) for which we haven't declared anything. We will do that in the children. But I would like to point out that BODY is somewhat special; because we will use it to mount content from children. We will come to that in a little while. Let us save this one as base.tmpl in the root directory of our project.
extend BODY "/base"
link MENU "/include/menu"
<div id="menu">
%(MENU)s
</div>
<div id="content-text-leftspace"> </div>
<div id="content-text">
%(CONTENT)s
</div>
Ok, this above is a template that uses the previous one (/base.tmpl) as parent. The extend header statement is used to assign a parent for templates. Each template can have zero or one parent. The variable name BODY preceeding is the mount point in the parent that this template will insert itself when rendered. Also notice that the file name extension is omitted in the parent template name (which is the case when we specify template names anywhere).
We will cover the link statement in the next section. We can just say menu.tmpl in include directory will be rendered and the result will be replaced with %(MENU)s for now.
Let's save this one as /text_page.tmpl (of course I assume you know that the slash in the beginning means project root directory and you won't include it in the file name). Now we have TITLE from /base and BODY from /text-page. BODY will be used as mount point for the templates that has /text-page as parent.
Now we can finally work on something that will generate output;
extend CONTENT "/text_page"
define TITLE " - Home Page"
output
<h1>Hi!</h1>
<p>Hello, I am %(MY_NAME)s. Wellcome to my site about↵
photography.</p>
<p>Of course some of you know me by my works, but for those of↵
you who doesn't know me here is a picture of myself working.</p>
<img src="/me.jpeg" />
<p>I like to work with the nature. I enjoy long hikes in↵
the weekends and bring lots of good pictures with me back.</p>
<p>I also work as an interior photographer for magazines.↵
Almost one thousand works of mine published in the most↵
respected architectural magazines over the last seven years.</p>
As we have seen MY_NAME is inherited from the parent's parent. In case of TITLE something different happens; it is defined down in a child template and the child's variables are passed up to the parent. To put this in simpler terms;
This also means that even if TITLE was defined in /base or /text_page its value would come from the define statement of the child template (" - Home Page" in this case).
Since we have an output statement in our template an output will be generated. Let's save this one as /intex.tmpl and run spg on it; (Of course you would need /include/menu and /include/menu_item as they are needed to render /text_page)
muhuk@pardus spg-tutorial $ spg.py .
written ./index.html
muhuk@pardus spg-tutorial $
Generated content would look like this;
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"↵
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" href="/main.css" type="text/css" />
<title>Bruno Gondolsk's Exceptionally Good Photography -↵
Home Page</title>
</head>
<body>
<div id="menu">
<nobr>
<span id="title">Bruno Gondolsk's</span>
<a href="/" title="Home">Home</a>
<a href="/about.html" title="About me">About me</a>
<a href="/photography/" title="Portfolio">Portfolio</a>
<a href="/contact.html" title="Contact me">Contact me</a>
</nobr>
</div>
<div id="content-text-leftspace"> </div>
<div id="content-text">
<h1>Hi!</h1>
<p>Hello, I am Bruno Gondolsk. Wellcome to my site about↵
photography.</p>
<p>Of course some of you know me by my works, but for those of↵
you who doesn't know me here is a picture of myself working.</p>
<img src="/me.jpeg" />
<p>I like to work with the nature. I enjoy long hikes in the↵
weekends and bring lots of good pictures with me back.</p>
<p>I also work as an interior photographer for magazines. Almost↵
one thousand works of mine published in the most respected↵
architectural magazines over the last seven years.</p>
</div>
</body>
</html>
Let's take a look at what part comes from where;
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"↵
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="stylesheet" href="/main.css" type="text/css" />
<title>Bruno Gondolsk's Exceptionally Good Photography -↵
Home Page</title>
</head>
<body>
<div id="menu">
<nobr>
<span id="title">Bruno Gondolsk's</span>
<a href="/" title="Home">Home</a>
<a href="/about.html" title="About me">About me</a>
<a href="/photography/" title="Portfolio">Portfolio</a>
<a href="/contact.html" title="Contact me">Contact me</a>
</nobr>
</div>
<div id="content-text-leftspace"> </div>
<div id="content-text">
<h1>Hi!</h1>
<p>Hello, I am Bruno Gondolsk. Wellcome to my site about↵
photography.</p>
<p>Of course some of you know me by my works, but for those of↵
you who doesn't know me here is a picture of myself working.</p>
<img src="/me.jpeg" />
<p>I like to work with the nature. I enjoy long hikes in the↵
weekends and bring lots of good pictures with me back.</p>
<p>I also work as an interior photographer for magazines. Almost↵
one thousand works of mine published in the most respected↵
architectural magazines over the last seven years.</p>
</div>
</body>
</html>
Colors mean; /base, text-page, /include/menu and /index.
(Since we didn't supply an alternate filename for the output statement it saved as the same name with out template.)
Alternatively we can supply a file name after the output statement, below is the output statement from the header of /contact_me;
output "contact"
In this case the output file will be /contact instead of /contact_me.
Linking
We have already seen how the link statement can be used to include another template's output in our template in the previous example. Now let's take a closer look at link and what we can do with it.
This is /image_page below. Nothing special, just to demonstrate how we can achieve different looks and still not repeating ourselves.
extend BODY "/base"
link MENU "/include/menu"
<div id="menu">
%(MENU)s
</div>
<div id="content-image">
%(CONTENT)s
</div>
Following two are /include/photo and /photography/index respectively;
define TITLE ""
define LINK_URL ""
define DESCRIPTION ""
<a href="%(LINK_URL)s">
<div>
<h1>%(TITLE)s</h1>
<img src="%(PHOTO_URL)s" />
%(DESCRIPTION)s
</div>
</a>
extend CONTENT "/image_page"
define TITLE ""
link P_NATURE "/include/photo" {'TITLE': 'Nature Photos',↵
'PHOTO_URL': 'images/pikes_peak_mountain.jpeg', 'LINK_URL':↵
'nature.html'}
link P_INTERIOR "/include/photo" {'TITLE': 'Interior Photos',↵
'PHOTO_URL': 'images/green_wall.jpeg', 'LINK_URL':↵
'interior.html'}
output
%(P_NATURE)s
%(P_INTERIOR)s
The photo template doesn't have a parent. But extending is taken into account for linked templates. Actually they are rendered like any other template. But because the main (or the current or the linking) template overwrites, and linked templates are rendered at the very last moment possible; you can take advantage on it and even overwrite something in the parent of the linked template.
Why did we define three of four variables in photo template and left PHOTO_URL out? Becasue we want PHOTO_URL to be a required variable and the other three to be optional. The emphasized part in image_page template shows how we can supply parameters to a linked template. These parameters have priority over what is defined in linked template. (Notation is very simple; you can use Python dictionary literals or JSON.)
With the paramters we supplied, TITLE and LINK_URL is overwritten and for DESCRIPTION the definition in /include/photo will be used. As PHOTO_URL is not defined elsewhere if you don't supply it somehow, as extra paramters for link statement or as a seperate variable, you would get an error.
Let's go back and take a look at /include/menu;
link MENU "/include/menu_item" [{'TITLE': 'Home', 'URL': '/'},↵
{'TITLE': 'About me', 'URL': '/about.html'}, {'TITLE':↵
'Portfolio', 'URL': '/photography/'}, {'TITLE': 'Contact me',↵
'URL': '/contact.html'}]
<nobr>
<span id="title">%(MY_NAME)s's</span>
%(MENU)s
</nobr>
...and /include/menu_item;
<a href="%(URL)s" title="%(TITLE)s">%(TITLE)s</a>
Instead of using the same template many times with different parameters (as in /photography/index) you can create a single link and give it a list of parameters (as in the menu example) to get concenated output of renderings with all the items in the list.
Let's take a look at /photography/nature;
extend CONTENT "/image_page"
define TITLE " - Nature"
link P_ZINGARO "/include/photo" {'TITLE': 'Zingaro Reserve',↵
'PHOTO_URL': 'images/zingaro_reserve.jpeg', 'DESCRIPTION': 'I↵
took this picture when I was hiking at Zingaro.'}
link P_PIKES "/include/photo" {'TITLE': 'Pikes Peak Mountain',↵
'PHOTO_URL': 'images/pikes_peak_mountain.jpeg', 'DESCRIPTION':↵
'This is my all time favourite nature photograph.'}
link P_WAITING "/include/photo" {'TITLE': 'Waiting',↵
'PHOTO_URL': 'images/waiting.jpeg', 'DESCRIPTION': 'He is...↵
waiting.'}
output
<h1>Nature Photos</h1>
%(P_ZINGARO)s
%(P_PIKES)s
%(P_WAITING)s
Now, we could write this using a paramter list like this;
extend CONTENT "/image_page"
define TITLE " - Nature"
link IMAGES "/include/photo" [{'TITLE': 'Zingaro Reserve',↵
'PHOTO_URL': 'images/zingaro_reserve.jpeg', 'DESCRIPTION': 'I↵
took this picture when I was hiking at Zingaro.'}, {'TITLE':↵
'Pikes Peak Mountain', 'PHOTO_URL':↵
'images/pikes_peak_mountain.jpeg', 'DESCRIPTION': 'This is my↵
all time favourite nature photograph.'}, {'TITLE': 'Waiting',↵
'PHOTO_URL': 'images/waiting.jpeg', 'DESCRIPTION': 'He is...↵
waiting.'}]
output
<h1>Nature Photos</h1>
%(IMAGES)s
This way we get one variable, the concenated values of three renderings with the parameters in the list.
Go ahead and try it!
I hope this tutorial has helped you understand spg. You can download the source and play with it. You can contact me at .
muhuk