Open GoogleCodeExporter opened 9 years ago
I just documented two template reuse patterns that I think are superior to
adding an
include feature:
http://code.google.com/p/json-template/source/browse/trunk/python/examples/reusi
ng_the_outside.py
http://code.google.com/p/json-template/source/browse/trunk/python/examples/reusi
ng_the_inside.py
There's an explanation inline with the comments.
Live examples are here:
http://chubot.org/json-template/cgi-bin/examples/reusing_the_inside.py/
http://chubot.org/json-template/cgi-bin/examples/reusing_the_outside.py/
(Note the trailing slash)
Let me know what you think. I'm going to write a "Design Minimalism" blog post
the
explains this point and another design decision (about the metacharacters).
One of
the virtues is that I'm trying to cover a lot of use cases with the bare
minimum of
features. This keeps the code size small, and lowers the barrier for
implementations
in other languages.
Original comment by gtempacc...@yahoo.com
on 1 Apr 2009 at 6:52
I wrote a very long-winded response to this (you weren't the only one to ask for
this; it was the most obvious hole):
http://json-template.googlecode.com/svn/trunk/doc/On-Design-Minimalism.html
If there's some problem you have that you those methods won't solve, or you
find them
deficient in some way, feel free to comment here. Closing for now.
Original comment by andyc...@gmail.com
on 5 Apr 2009 at 7:53
Sorry I just have to press on for my idea. Though not in the same incarnation
as it
was originally.
After first seeing your response on my blackberry I could not really read the
full
examples normally, but it got some gears turning in my head, after reading your
inside method I think I finally refined what exactly we want to do... There is
still
one major limitation which cannot be resolved by either methods I provided OR
you.
Formatter parameters is the necessary features... example:
{userProfile|template(user/profiles/v1.tpl)}
I think you can pretty much see where I am going with this. This is a slight
modification of the inside pattern that you have except that I don't need to
specify
EVERY type of template inclusion fomratter I will ever need globally, instead I
just
create a "template" formatter which finds the template files in the way that I
define
in my server. I just need the ability to pass it parameters like which template
to
render.
Now for the problem with all methods (and this is more of a nice-to-have than a
necessity like the formatter parameters):
Each template has different .js and .css requirements. It would be great if I
could
have templates really define "what they need" to work. Without the includer ever
having to know/care about it (leaky abstractions but you get the idea).
Example:
Page1 (shell) -- no requirements.
user-summary.tpl (inner template) -- user-summary.css, user-summary.js
requirements.
the inner template wants to tell the shell that where it renders .css files it
must
also render user-summary.css, where it renders .js files it must render
user-summary.js.
The question is: Do the dependency statements that I describe above fit in with
the
JSON template philosophy or do they go somewhere to the side?
Original comment by dlikhten
on 5 Apr 2009 at 4:46
Ah I just added that to the article! Someone else didn't like the level of
indirection between formatter names and templates. I used the % character, but
there's no reason you can't use template(<filename>) -- since formatter names
are raw
strings that the application interprets. (See the second definition of
MoreFormatters)
I didn't even realize this at first, but this scheme is turning out to be quite
flexible.
Good point about .js and .css dependencies. Perhaps we could define extensible
metadata per template. There already is constructor metadata
(FromFile/FromString).
I'll have to think about this a bit. Do other template systems have a solution for
this problem?
But try out the first thing and see if it works for you.
Original comment by gtempacc...@yahoo.com
on 5 Apr 2009 at 5:47
You do have a nice point about the fact that MoreFormatters in your inner
example can
easily parse out the template\((.*)\) and keep going. I just feel that maybe
that's
what the framework should provide. I see this construct being useful for other
cases
beyond simply templates. The way the formatter function could be constructed is:
MoreFormatters(format,args /* an array */ )
Definitely a recipe for template inclusions should be specified in the API for
the
framework. I realize this is not "part of the framework" but it is just as
important
as it might not be immediately obvious to people about how to approach this
when they
first see JSON template.
Regarding dependencies... Ruby on Rails has a sort-of kind-of thingy like this.
Basically the <% yeild for='foo' %>
So my shell can have:
<html>
<head>
<% yield for='css' %>
...
<% yield for='js' %>
</head>
<body>
<% yield %>
</body>
</html>
Or something similar sorry the ruby syntax is fading from my brain I haven't
used it
in over a year.
However that is NOT what I meant... its more of a repeating section in how JSON
template defines it... my ideal solution quickly manifested, I haven't given
this
syntax much thought but hopefully it illustrates what I am trying to get at.
<html>
<head>
<!-- some css that is statically included in the page -->
<link ...>
{.dependencySection css}
{.repeat section @}
<link rel="Stylesheet" media="{media}" href="{server-base}/{relpath}">
{.end}
{.end}
<title>Hello Templating World!</title>
<!-- some js files that are statically included -->
<script type="text/javascript src="{server-base}/..."></script>
{.dependencySection js}
{.repeat section @}
<script type="text/javascript src="{server-base}/{relpath}"></script>
{.end}
{.end}
</head>
<body>
{mainData|template(foo.tpl)}
</body>
</html>
Original comment by dlikhten
on 5 Apr 2009 at 6:17
Yeah I do see the need for standardization around the formatters. Actually the
syntax I chose in example was bad, because the %filename syntax conflicts with
%.3f
Python formatter syntax I had written earlier. So those could be expressed:
{var|template(filename)} and {floating-point|printf(%.3f)}. If people like
brevity
they can always define their own syntax, but there should be a standard one.
I would make this another module next to jsontemplate.py, called formatters.py.
And
then we can add all the common use cases there, so that everybody doesn't invent
their own.
To get real reuse, I think there might need to be some higher order function
chaining, like:
Template("...", more_formatters=Chain([formatters.FileLoader('root-directory'),
formatters.PythonPrintfFormat()])
or something like that. Now you can include template() and printf() as
formatters.
Are you interested in providing a patch for this?
-----
As for the dependencies, did you look at the example linked in the Design
Minimalism
article about how it's generated? That already has repeated sections for js
and css.
There's no need for another section type there.
Is the issue that you want to package the .css and .js paths (which are part of
the
data dictionary) in the same file as the template?
Original comment by gtempacc...@yahoo.com
on 6 Apr 2009 at 12:32
Dependencies is more along the lines of, an inner template specified what
dependencies it has (it knows how the outer template accepts data, but that's
it) and
the outer template will render the inner's dependencies.
An example is the html skeleton which defines where .js and .css files go, but
user-summary.tpl needs a js and css file, so it gives those two to the outer
template
to be placed in the header. Sort of like a static JSON object declaration. This
is
NOT part of the JSON data given to the template, it is purely a construct
inside the
templates.
As for template... I just want a parametrized formatters pattern. This way I
(working
in a javascript server) can implement how to retrieve other files. Actually I
never
had a need to do python programming (a good time to start is now :) but I might
be
really slow making these python implementations :(, or I can make the
javascript side
and you can port to py). However once you have the parametrized stuff that
detail is
removed from things like printf(%0.3f)
I like the printf idea as well, definitely helps since it handles most
necessary cases.
My idea of the template formatter is to have it ask for a file finder function
which
takes a path and finds it. We can have a default one for django or w/e, its
just that
each web server has their own methodology of how to find files, so it might be
problematic to actually implement a real finder.
Original comment by dlikhten
on 6 Apr 2009 at 1:53
Sorry to add to the above... Once we have parametrized formatters, we can just
give a
recipes page of all sorts of cool recipes people come up with when designing
JSON
template. These recipes will be things you (or the community) decides are
necessary
but don't need to be in the language.
Original comment by dlikhten
on 6 Apr 2009 at 1:57
OK, well if you want to hack something up for the JavaScript version, I'll look
at it
and implement the Python version. I think that in both cases it should be a
separate
module. Particularly in the JavaScript case, people care about download size.
Do you see what I'm saying about the chaining? The compiler has resolve a
formatter
string to an actual formatter, so first it will try "template()", and then
"printf()", etc. So we would have to compose functions to create a single
more_formatters= function.
I agree about having "recipes"; there should be a standard set. The thing is
that
all implementations won't always be in sync, so it's important to have a
standard to
follow.
Django already has a large list of formatters. Where possible we should borrow
them
(but they're not all named greatly):
http://docs.djangoproject.com/en/dev/ref/templates/builtins/#add
Original comment by andyc...@gmail.com
on 6 Apr 2009 at 4:19
Since currently the only way to make custom formatters is to have one, we need
to
chain... Right.
Right we can give the users the ability to make their own formatter lookup and
whatever funky syntax they want, or use the default to add multiple formatters
and
use them by a key lookup. Definitely a necessity as well.
May I recommend we take this discussion off the bug post and post a strategy as
the
next comment? This is turning into a back-and-forth conversation. Email me at
gmail.
Original comment by dlikhten
on 6 Apr 2009 at 5:08
Yeah let's take this to the discussion list. There are enough people on it
that they
might provide some feedback.
Original comment by andyc...@gmail.com
on 6 Apr 2009 at 7:48
Original comment by gtempacc...@yahoo.com
on 7 Apr 2009 at 3:17
We've agreed on a way to do this -- it still needs to be implemented in
JavaScript
and documented everywhere.
Original comment by gtempacc...@yahoo.com
on 10 Apr 2009 at 12:29
I recommend implementing a simple template recursion feature such as in
StringTemplate. On the other hand, I strongly recommend against the idea of
tracking
dependencies between templates as described here. Please allow me to explain...
My desired usage scenario is that I want a simple API for creating an empty
instance
of a template, assembling and inserting my data, then rendering the template
with
that data to obtain a String. The template engine should be aware of and
properly
handle character encoding, probably by forcing me to declare the encoding of the
template(s) prior to loading.
So, I should be able to do something like the following:
instance = template.create("name")
data = ...(whatever I want, independent of the template API)...
output = instance.render(data)
A crucial feature of this approach is that I should be able to refactor the
template
"name" as much as I want without having to edit the code to use it. In
particular, I
should be able to refactor gracefully from a template in a single file (known by
"name") to splitting the template up into as many named pieces (separate files)
as I
want. Typically, template "name" represents a single web page, report, or
whatever
other output that I desire.
This feature necessitates a means of invoking the template engine with a
configuration for finding all the template pieces. This might mean a
constructor
that takes a directory (with named templates as files within the subdirectory
tree).
This might mean a single file with templates as named sections within it. This
might mean a constructor for the template engine that creates an empty template
holder that allows the user to add named templates at will, via whatever
mechanism
that the user chooses. In JavaScript, the engine could make AJAX calls to
request
empty templates by name from the server (where relevant).
As a consequence, each template instance must have a parent object that knows
how to
resolve and provide any references to other templates. StringTemplate does
this via
a StringTemplateGroup.
However, one of StringTemplate's problems is that the API has gotten way too
complex,
in large part because of this addition of the StringTemplateGroup, plus some
special
syntax to support it, etc. I STRONGLY advocate for keeping your template
language
and the API simple and clean. In particular, if you add such a feature then I
would
make it a separate deliverable/artifact that is optional and separately testable
(which StringTemplate did not do).
As for the whole dependency thing, I consider it to be a nonissue. If I am
templating a web page, then the browser will trigger the rendering of the HTML
template by the initial web request. When the browser finds a reference to the
"external" CSS file, then that web request will trigger the rendering of the CSS
template. Likewise, the reference to the "external" JavaScript file in the HTML
template will trigger a web request for the JavaScript template. If I edit the
HTML
template to no longer reference the "external" CSS or JavaScript, then the
browser
won't find them and it won't issue web requests for them. However, I want to
be able
to make that CSS and JavaScript internal by replacing the "external" references
with
"internal" references to the same (sub)templates. I should be able to switch
back
and forth between those implementations without changing my code, and I can with
StringTemplate.
However, StringTemplate has gotten too complex and they seem to have lost sight
of
the real usage patterns, so their test suite is incomplete and does not
adequately
cover these features. Therefore, in recent versions, this behavior has become
buggy
and the code base has become bloated.
I think that we can avoid a repetition with json-template, and I am committed to
helping do so.
Best wishes...
Original comment by Robert.David.Williams
on 14 May 2009 at 7:38
You know I think you'll be pleased with the reuse mechanism(s). It satisfies
the
properties you request, and the API for JSON Template is still dead simple.
The key is that the include mechanisms are implemented as a special case of
"formatters". It's completely on top of the engine, and user configurable. I
wrote
the file system include mechanism in formatters.py, but you can also write one
that
does AJAX calls, etc. like you said. All without modification of the API.
Definitely read this if you haven't:
http://json-template.googlecode.com/svn/trunk/doc/On-Design-Minimalism.html
The implementation now basically a demo, and not really "standardized". But
the idea
is all there. I think it's too early to standardize; we need some more feedback
based on actual usage.
I hadn't seen StringTemplate until now. It sounds like it has some of the same
problems in mind. But I took one look at this page:
http://www.antlr.org/wiki/display/ST/StringTemplate+Documentation
And my initial thought is that it's way too complicated.
It's interesting that there's a paper about how it's a functional language:
http://www.cs.usfca.edu/~parrt/papers/ST.pdf
I'll have to read this sometime. JSON Template is also a functional language
as I
wrote in that article... in particular all language constructs can be evaluated
in
any order whatsoever.
Original comment by andyc...@gmail.com
on 15 May 2009 at 5:39
Done in JS and Python
This is the FunctionRegistry set of APIs
Original comment by gtempacc...@yahoo.com
on 7 Nov 2009 at 9:26
Original issue reported on code.google.com by
dlikhten
on 30 Mar 2009 at 5:35