- Type safe HTML: you get an exception instead of malformed HTML
- Truly reusable components: any Python web framework, component packages are truly reusable in any other projects. I never seen this with template engines.
- Huge productivity boost: not even close! No hunting for templates, no jumping between files, everything is in Python functions.
- Composable elements: you can nest things as much as you want, refactor very easily. Doing this with templates is not even possible, or such a pain I never did it.
- Storybook: There are a couple ones for Django, but they are clunky and not reusable at all.
I felt the same for a long time, but started thinking about a nice API. It took me months, but I finally got it: https://github.com/kissgyorgy/compone
Yes, I quite like the idea of being able to run pyflakes/flake8/black/pytest/mypy over my "html templates", and benefiting from all the power that entails.
It may hurt your eyes at first sight, for sure... But similarly to technologies like Tailwind CSS, it's mostly a matter of getting used to it - and after a while it end ups feeling very natural to use :-)
I imagine a lot of this comes down to personal preference. In the early days of Mountaineer [^1] (gee, almost two months ago at this point), I played around with the idea of embedding html into python instead of needing a JS layer. Eventually my consensus was:
- The most flexible shim approaches typically end up wrapping JS/React components anyway (like Reflex/Pinecone)
- We really need better IDE support for html strings that are within python strings. The editing problem is a big setback.
The ergonomics of Python + JS in separate code files won out and the user experience has been better than forcing them both into a common language would be.
This has the benefit of leveraging whatever the two languages are best at, in native code, so you have access to all the native APIs without having to learn a shim on top of it. Way more longevity to that approach too. Context switching between two languages isn't that bad if you minimize the glue layer that you have to write between them.
I agree and I don't fully understand the why of it.
I remember coding PL/SQL to emmit HTML in Oracle around 1999 or 2000 and using functions to code the various elements.
That got old and repetitive very quickly - for instance, everytime I had to correct a spelling error, I had to recompile the code.
To get around it I used one or two tables to hold html snippets to decouple the business/backend logic from the frontend, and stopped using the PL/SQL functions completely.
My speed of developmet skyrocketed, and separating and abstracting the frontend from the backend made so much sense.
A few years later, I was doing web developemt with Python using the Zope framework (not many people know about it tiday, I think).
It uses a specialised serverside templating language called TAL (Template Attribute Language)[1] that basically builds the front end dynamically, and then you feed it data from the backend.
Very neat and allowed me to build reusable compoments as well as collections of a schema definition (basically a dict), html template(s) and the code to validate that the input matched the schema and could be rendered.
Or something like that - its been 2 employers and almost 20 years since I worked with that :)
I did build a small extension for Wordpress using a PHP implementation[2] of TAL a few years ago, and TAL still works like a charm :)
My point is that I still believe there is value in keeping python out of the html-templating, and in keeping the front end logic apart from the backend logic.
There is something I am not understanding about the renewal of mixing HTML/GUI template with code, but I haven't fully found it yet.
Yeah, I understand that. Now that Python 3.12 has better support for f-strings, I thought there might be a way to make it possible. But I am still not sure it will work. There is a pretty weird hack to make f-strings work while avoiding the possibility of rendering unsafe user input.
It's nice for small hacks, but for anything longer than a couple dozen characters you're probably still better off making jinja2 (or similar) templates as painless as possible.
In general, this usually results in front-end logic being very tightly coupled with back-end logic. In some of the examples given, you even have database access in the same line that is generating the HTML document.
> In some of the examples given, you even have database access in the same line that is generating the HTML document.
Python template engines have the exact same problem, just way less obvious.
It doesn't have to be that way. Make all the queries up-front and pass the result the same way as you would pass context to templates. This way, all your components are pure. The difference is explicitness. Much easier to spot where side-effects happen than in templates.
I think the issue is orthogonal. I'm not a huge fan of react but it's an example of an architecture where the structure that is (imposed/encouraged) helps avoid the problem you're talking about.
I don't think the issue is "markup expressed in another language" - I think it's "poor application architecture". I don't dispute there might be a correlation between libraries and frameworks that do poorly on each - but that doesn't mean it's intrinsic.
- Type safe HTML: you get an exception instead of malformed HTML
- Truly reusable components: any Python web framework, component packages are truly reusable in any other projects. I never seen this with template engines.
- Huge productivity boost: not even close! No hunting for templates, no jumping between files, everything is in Python functions.
- Composable elements: you can nest things as much as you want, refactor very easily. Doing this with templates is not even possible, or such a pain I never did it.
- Storybook: There are a couple ones for Django, but they are clunky and not reusable at all.
I felt the same for a long time, but started thinking about a nice API. It took me months, but I finally got it: https://github.com/kissgyorgy/compone