- the broken mix of pythonisms
- the arbitrary-feeling restrictions
- the oddly missing pieces
Because I can't find any.https://github.com/pallets/jinja/issues/659
> It was never documented that you can override variables from higher scopes
But you could, and people did... because that's what people do: they try stuff that seems reasonable and if it works they use it. And then someone "fixed" it in a minor release and things started breaking. BTW the error message is
KeyError: 'undefined variable: 0'
Fun way to spend an afternoon, I can assure you.I used Jinja2 happily for years on a web app, but that thing pretty much just styled a page for flash to sit in and drew some forms and menus. I use it now via Ansible and have come to despise it through and through.
I'll try to find it again. I obviously ditched the
From what I've seen of other template languages, it resembles Mako the most, though some of the syntax superficially resembles Jinja2.
So if you want to replace a character in a string, that's fine, because `replace` is an instance method:
Changed plus to dot: {{ string.replace('+', '.') }}.
but if you want to take the length of that string, you need a Jinga-specific filter to have been implemented, because getting the length is via a global function `len()` in Python. This fails: My string is {{ len(string) }} long.
If you're just using Jinga to build some HTML or whatever and you were always in your own Python code right before the template it's not really a problem, 'cause you can just do it in said Python code. I happily used Jinga for several web apps for years.I really started to hate it in Ansible though, where I'm often just trying to get a one-off little operation done that I would rather have obvious right there in the template source rather than having to bounce over to a one-off filter function (or invoke some other outside code), and I can do it in Jinja, but it just looks and feels like hell... which kinda defeats the purpose.
I feel like Jinja was an especially bad fit for Ansible, but as a templating language I feel like it's main strength is it's better than D'jango templates... but that doesn't matter much outside the D'Jango world.
As a logic-ful template language I think it's deficient because it omits the functional parts of Python, which - as discussed above regarding `len()` - are very core to Python, and Jinja adds them back in a different way that requires extra mental overhead to keep track of. I really like the pipes (filters) but it would have been nice to just keep the Python globals as well for consistency.
And if you really want to go logic-less with your templates, I think Mustache(-variants) would be the way to go since they're much more truly "logic-less" and they're supported across a plethora of different runtimes besides Python, giving your much more flexibility. I've never really had the patience / discipline / right use case for logic-less though, so I'm far from an expert in this area.
Jinja is just a really weird mix... it's not logic-less, but it's not Python... it's a funky half-logic mishmash. It obviously makes sense and feels right to the people that make it, and if it makes sense and feels right for you that's awesome, but I hope you can understand how could feel awkward to others.
The main dlang web framework, vibe.d, uses a 1:1 copy called "diet" templates (You can insert D code to be run on the server, with the arguments given to the HTTP request/response). This works very well IMO, mainly because D is a very good programming language, so you can mix very fast / expressive D code with your regular JS for client side work.
.sep
vs <div class="sep"></div>
So short and concise! And the "somehow" isn't that magical... The code you right else where ultimately gets transformed into something else, too!What I like most about it is that i can just use Nim code in my templates. I can't say the same for Django templates or (I guess) Jinja.
One peeve: managing multiple partials for a single page with mixins seems a little more complicated than necessary.
It is impressive though how often you have types when I wouldn't expect it.
JSX is a data structure with a syntax similar to XML. The angle brackets are quite similar to brackets around any other data structural literal in any other syntax.
The tag names are references to either in-scope variables/constants (when capitalized), or references to a static set of HTML element names specified by React (when lowercase). This is different from HTML or even XML because they are evaluated at runtime (plain JSX->JS compilation) or validated at compile time (e.g. TypeScript).
The attributes names are keys in the data structure's props, and the values are either static (if specified as string literals) or dynamic (if specified between curly braces). These too can be checked at runtime (with PropTypes) or at compile time (e.g. TypeScript).
By specifying dynamic props (or conditional children), the component will re-render as the values change.
I'm not aware of any other HTML-like or XML-like template language which functions the same way.
Edit: I forgot to mention, dynamic props are also exactly JavaScript/JSX expressions. Basically JSX is a macro that turns the XML-like stuff into React API calls.
The primary restriction is that your output can be modelled as a tree in some way, and what you find is that nearly everything falls into this category. I don't know if anyone's done it yet, but a plain-text renderer is certainly possible, I imagine it would be very similar to a terminal renderer.
JSX transpiles down to a tree of function calls, it's literally nothing more than that, the only time it might be considered XML is in the final rendered content. Syntactically, JSX isn't even valid XML.
(This is also why "templating languages" in PHP were a special kind of foolish; PHP is a templating language.)
Any PHP project of any reasonable complexity will either use an existing "templating language" (by which you probably mean a framework) or be forced to create some sloppy, ad-hoc version of one, because while yes, PHP is a templating language/framework, it's also a terrible one.
Emitting HTML is no different from any other functional programming task. State in, HTML out. (You had to be a little clever because you had to ob_start/ob_get_buffers/ob_end, but whatever. Still better than the alternatives.)
What hard things, specifically? I've used Twig a lot and never found it to get in the way of anything else I was trying to do.
>You had to be a little clever because you had to ob_start/ob_get_buffers/ob_end, but whatever.
By the time you have some general abstraction to push "state" into and get "HTML" out of, and deal with output buffering, header management, etc, you've started building an ad-hoc framework.
> By the time you have some general abstraction
Sure. It's about a dozen lines long. And the language is the actual language I'm working with, not something that needs its own parser to give me less functionality in the spirit of mollyguarding on behalf of people who make mistakes of classes I categorically refuse to allow in my systems. (Please don't mistake this as me saying "I don't write bugs." I write many, many bugs. But I structure programs such that some bugs are very, very hard not to make obvious and to avoid.)
For similar reasons, this is why almost all of my web stuff these days uses a Node backend and a React/JSX or React Native frontend. Consistency across the whole thing, buttressed by tools that encourage good practice without chopping you off at the knees.
Ok. But to be fair, Twig's parser is extensible, whereas PHP's isn't. And it lets you use array shorthand in PHP versions that don't support it (which is not as much of a problem as it used to be, but to me, more than worth never having to type "Array()" again.)
Have you tried the XHP functionality in Hack? It treats XML as objects and understands it in context (which is something PHP should do natively, but can't.) It seems to solve many of the footgun problems that PHP template languages do, within native code.
It's another tech that renders just as well on the client as the server.
I'm not sure that's the template language's fault and more than Python is responsible for Python code that goes metaclass happy for no reason.
The brute-forceable admin happened around the time web2py and Django devs started having a few arguments online, like this one [1], which didn't exactly paint web2py in a good light.
[0] https://security-tracker.debian.org/tracker/source-package/w...
[1] https://www.quora.com/Is-web2py-a-good-Python-web-framework