Dynamic directory trees templates¶
Directory trees can be computed from templates.
Thus you can use all features of template engines to render filenames, select templates or even alter context.
Note
In the examples below, let’s communicate with a diecutter server using Python requests.
This diecutter serves diecutter’s demo templates.
The diecutter_url
variable holds root URL of diecutter service, i.e.
something like http://diecutter.io/api/.
Use cases¶
While rendering a directory...
- skip some files based on variables ;
- render a single template several times with different output filenames ;
- alter template context data for some templates ;
- use loops, conditions... and all template-engine features...
The template tree template¶
When you POST to a directory, diecutter looks for special ”.directory-tree” template in that directory. If present, it renders ”.directory-tree” against context, decodes JSON, then iterates over items to actually render the directory.
Except when rendering a directory resource, ”.directory-tree” template is a normal template resource file. Manage it as any other template file.
Example¶
Let’s explain this feature with an example...
Let’s work on directory resource dynamic-tree/
.
>>> dynamic_tree_url = diecutter_url + 'dynamic-tree/'
It’s a directory. So GET
lists the templates it contains:
>>> response = requests.get(dynamic_tree_url)
>>> print response.content
.directory-tree
greeter.txt
greeter.txt
is a template, with nothing special:
>>> response = requests.get(dynamic_tree_url + 'greeter.txt')
>>> print response.content
{{ greeter|default('Hello') }} {{ name|default('world') }}!
directory-tree
is a also a template, with a special name:
>>> response = requests.get(dynamic_tree_url + '.directory-tree')
>>> print response.content
[
{% for greeter in greeting_list|default(['hello', 'goodbye']) %}
{
"template": "greeter.txt",
"filename": "{{ greeter }}.txt",
"context": {"greeter": "{{ greeter }}"}
}{% if not loop.last %},{% endif %}
{% endfor %}
]
directory-tree
template renders as a list of templates, in JSON:
>>> response = requests.post(dynamic_tree_url + '.directory-tree',
... {'greeting_list': [u'bonjour', u'bonsoir']})
>>> print response.content
[
{
"template": "greeter.txt",
"filename": "bonjour.txt",
"context": {"greeter": "bonjour"}
},
{
"template": "greeter.txt",
"filename": "bonsoir.txt",
"context": {"greeter": "bonsoir"}
}
]
JSON-encoded list items are dictionaries with the following keys:
- “template”: relative path to a template, i.e. content to be rendered ;
- “filename”: filename to return to the client ;
- “context”: optional dictionary of context overrides.
When rendering a directory, diecutter first computes the tree of templates
in the directory. By default, it just reads the filesystem. But if there is a
.directory-tree
file, then this special file is rendered first, and the
result is used as the list of templates to render.
So, when you render the directory, you generate the files according to the
generated directory-tree
template:
>>> response = requests.post(dynamic_tree_url,
... {'name': u'Remy',
... 'greeting_list': [u'bonjour', u'bonsoir']})
>>> archive = tarfile.open(fileobj=StringIO(response.content), mode='r:gz')
>>> print '\n'.join(archive.getnames())
bonjour.txt
bonsoir.txt
>>> print archive.extractfile('bonjour.txt').read()
bonjour Remy!
>>> print archive.extractfile('bonsoir.txt').read()
bonsoir Remy!
>>> archive.close()
Here, the greeter.txt
template has been rendered several times, with
different context data.