bottle icon indicating copy to clipboard operation
bottle copied to clipboard

rebasing to templates defined as a string.

Open allanderek opened this issue 11 years ago • 8 comments

Currently one can do:

welcome_template = """<h1> Welcome</h1>"
...
return bottle.template(welcome_template, ...)

and all works fine. However it would be nice to be able to do:

root_template = """<html><head></head><body>
%include
</body></html>"""

welcome_template """<h1> Welcome </h1>
%rebase root_template title="Hello"
"""
...
return bottle.template(welcome_template, ...)

But you cannot do that since root_template will not be found. So you're forced to put root_template into a file root_template.tpl

allanderek avatar Jul 04 '13 13:07 allanderek

+1 Why have string templates when they're artificially limited like this?

Messy workaround for now is to insert root_template into welcome_template's cache manually before rendering so as to circumvent the whole file search & read operations:

# ... Code to initialise welcome_template and root_template here ...
welcome_template.cache["root_template"] = root_template
# ... Render code here ...

f10f0bfbd87448 avatar Jan 09 '15 15:01 f10f0bfbd87448

I'd argue that rebasing from a string template is as weird as including one, since a rebase gets translated to an include:

Foo: {{foo}}
% # hypothetical api change allows the following
% include("Bar: {{bar}}", bar=foo.bar)

Why would you ever want to write that, over:

Foo: {{foo}}
Bar: {{foo.bar}}

There seems to be no point in adding this feature.

eric-wieser avatar Jan 09 '15 16:01 eric-wieser

I'm not sure if I understand your objection correctly.

Rebasing is commonly used for "template inheritance", just like it is used in the OP of this issue: You have a common template and then specialised templates that are inserted into this common template via rebasing. Of course this is possible with regular variable substitutions, but it's quite awkward since you have to do the whole composition manually in the render step:

root_template.render(base=welcome_template.render(a=1, b=2), c=3)

This gets hairier for situations with more nesting.

I don't see why there should be any difference between string templates and file templates for this use case.

By the way, I noticed the OP is talking about the rebase keyword, while I'm talking about the rebase function that was introduced in a more recent version.

f10f0bfbd87448 avatar Jan 09 '15 16:01 f10f0bfbd87448

I was getting confused by the lack of syntax highlighting and syntax error by the OP, and assumed I was looking at tpl code not raw python. Oops.

I now understand that the premise is "All my templates are inline strings in a python server, and I want everything to work as if they were in separate files".

I think the solution here might be to allow registering of string templates to a global name, which is essentially what your hacky solution is doing anyway.

This gets hairier for situations with more nesting.

Can you give me an example of when I'd want to %rebase() twice? I've never done that, and feel I might be missing a trick

eric-wieser avatar Jan 09 '15 16:01 eric-wieser

Can you give me an example of when I'd want to %rebase() twice? I've never done that, and feel I might be missing a trick

I have a situation where I have a root_template common to all pages (basic HTML + CSS skeleton, etc.) and then some pages with similar but slightly different templates. One idea is to take their commonalities and put them in a template (let's call it x_template) that rebases from the root_template. Each sub-page in turn gets its own template which rebases from x_template. Other pages that are "one of a kind" rebase directly from root_template.

It's exactly what one would do if we were talking about classes instead of templates.

I agree that this can be / is a messy solution in its own right, and only works for the simple case of commonalities that "wrap around" the special parts.

I suppose I'm better off composing the templates manually in the render step instead of doing nested rebase.

f10f0bfbd87448 avatar Jan 09 '15 17:01 f10f0bfbd87448

+1 for adding this feature. It would greatly help with command-line experimentation and with putting small template patterns into self-contained scripts.

See: https://stackoverflow.com/questions/46680524

rhettinger avatar Oct 14 '17 01:10 rhettinger

Would not be that hard to do. Just copy a bit of logic from bottle.template() to bottle.SimpleTemplate._include.

But I'm worried about users that think it's okay to pass dynamically created template strings to rebase() or include(). This would quickly bloat the cache with templates that are only rendered once and make everything horribly inefficient. Perhaps emit a warning if the cache grows to big?

defnull avatar Oct 14 '17 09:10 defnull

+1 any update about this?

codeawn avatar Mar 05 '24 04:03 codeawn