fragment caching for jinja2 templates - python

I‘m trying to improve the rendering performance of my jinja2 templates in the context of Django (changing from the django engine to the jinja2 already gave a significant increase of around 5 times quicker rendering time).
For context, I have a quite large template where major sections stay always the same making them suitable to the idea of caching. Then the other remaining sections within the template will almost always be different to the previous call making them less suitable for caching.
I had the idea of splitting my template so that there is a base template (with the non changing sections) and the child template which extends the base template with the dynamic sections. The idea behind this was that the base template is cached, however I could not find any documentation which would validate this idea.
The other approach I came across is template fragment caching (https://docs.djangoproject.com/en/3.2/topics/cache/#template-fragment-caching) which looked promising, but I was not able to get my head around on how to achieve this result using the jinja2 engine.
I would like to do performance tests for both approaches, so was therefore looking for guidance on how to achieve fragment caching with jinja2 and validation if the base template is cached separately.
Is the base template cached separately when using the extend mechanism in jinja2 templates?
edit: changed to more explicit question following comment

Related

Django: Implementing a nested, reusable component design

I'm working on a big social networking app in Django where I expect to use certain front-end components many times, and often with functionality designed in such a way that custom components contain other custom components, which might contain yet smaller subcomponents (ad infinitum). All of these components are typically dynamic generated. I'm trying to figure out the best way to architect this in the Django framework, such that my components are easy to maintain and have clear programming interfaces. Relying heavily on global context would seem to be the opposite of this, however, I can see advantages in avoiding redundant queries by doing them all at once in the view.
Custom inclusion template tags seem like a good fit for implementing components, but I'm wondering, do highly nested template tags can create performance issues, or does the parsing architecture prevent this? What is the best way of making it self-documenting at the view level what context is needed to render the main page template, custom tags and all? I'm imagining it to be a minor nightmare to try to properly maintain the code to set up the template context. Lastly, what is the best way to maintain the CSS for these components?
Feel free to suggest other recommended approaches for creating a nested-component design.
The solution I've decided on so far is to go ahead with using an inclusion tag library as my set of reusable components. I'm sticking as much as possible to setting up all queries in my view code, and passing them in pre-setup in my context--no functions that generate new queries in templates or tag library code. The inclusion templates contain all of the markup for the item, and the styles go into the main site stylesheet, keeping my classes as generic and reusable as possible, following the guidelines of SMACSS. I refactor components into inclusion tags only as DRY requires.
I initially made my inclusion tag functions explicitly take the parameters used by the tag template, such that:
Page template
<div>{% my_tag param1 param2 %}</div>
Tag library
#register.inclusion_tag('myapp/tagtemplates/my_tag.html')
def my_tag(param1, param2):
return {'param1': param1, 'param2': param2}
my_tag.html
<div>Blah: {{ param1 }}</div>
<div>Blip: {{ param2 }}</div>
...and obviously the view sets up the context.
But I decided instead to use the takes_context parameter to avoid explicitly defining the parameters in the tag library. Too much repetition for not enough payoff in documentation. So far, my components are simple enough that the dependencies are pretty clear from inspection of the tag template. I worry that this might not be acceptable with complicated nested components, but I can always make my tag library functions verbose, where they need to be.
I'm not entirely pleased with this setup from a maintenance standpoint. I don't like that I will have to manually track what context data is no longer needed. I don't like the fact that my CSS classes will have to be carefully named to avoid clashes.
I am still open to new solutions, because I'm not sure that what I've decided really is a best practice.
It is an interesting problem. Ideally you should pull all the components from database before rendering. But looking at hierarchy, making template tags makes sense. These template tag will pull appropriate data. Assume for the purpose of this problem that database query gets cached due to search locality.

Can chameleon support block caching?

I'm evaluating chameleon as a template renderer for Pyramid.
Some feature quite useful from Django, which also works with mako, is caching.
I couldn't find a similar feature by looking at the documentation, neither with a quick google search.
Is there a similar feature with Chameleon ? If not, how can one deal with potentially long template rendering ?
There is no built-in support for caching the rendered result of a Chameleon template.
There seems to be support for Beaker together with Pyramid. The thread below discusses that implementation.
http://groups.google.com/group/pylons-devel/browse_thread/thread/efe8fd52e6643c47/2675c7098bb32413

Pyramid: simpleform or deform?

For a new (Python) web application with the Pyramid web framework, I'd like to use a form binding and validation library and so far found simpleform and deform. Does anyone have experience with these, and can tell me why I should pick one or the other? I am not using an ORM, just POPO's so to say.
I think I would prefer the easiest for now.
I've not had extensive experience with either, but so far this is what I've learned.
They both use colander (which I very much like) for definition and validation of forms. In my opinion what really sets them apart is their rendering mechanisms. In this regard, deform is the most straightforward in the sense that it allows you render the whole form by just doing form.render() in your template. On the other hand, with simpleform you must render each field manually. This could be either a good or bad thing depending on what you need.
A drawback with simpleform is currently there is no clear way to handle sequence schemas in templates.
edit: Also, in my opinion, deform has better documentation available.
I haven't used simpleform yet, but I have been using deform for a project I'm currently working on. deform allows you to render templates from a colander schema, which is very handy. Also, if the schema is violated you can simply call ValidationFailure.render() (after catching the ValidationFailure exception) and a message that you can customize is rendered with the form. I'm currently grappling with the choice between rendering the entire form and rendering it piece by piece. It would be really nice if you could group components together for rendering.
Though it's a third alternative, but have you considered ToscaWidgets2?
From a quick glance on simpleform and deform, it seems to me that Toscawidgets2 is the golde middle between those two in case of features and simplicity.
There's even a tutorial for using it with Pyramid, just drop the database part and supply the form values as a dict.
For your information, deform is used by :
Kotti : http://kotti.readthedocs.org/en/latest/
Substance D : https://substanced.readthedocs.org/en/latest/

Since Django discourages passing arguments to functions in templates, what is encouraged instead?

I understand that in Django, the template language is purposely neutered to prevent too much computation in display code. It means that, ideally, for every situation where users might feel compelled to do computation, there's a more proper alternative. Either a tag or filter that does the trick, or something hopefully straightforward in the view. Any annoyances that don't fit into here are hopefully rare.
But I've found a common case that is rather annoying, and either Django has a better way to do this that I haven't thought of, or they ought to see the light here and move the line a little bit on computing within a template in a near future release (as they did with if statement parameters, for instance):
I have a queryset of items. I need to display them somehow, but what I display depends not only on the state of the object, but also other independent things (usually who is logged in). So adding a function to the model won't help.
What I've been doing so far is turning the queryset into a list or tree structure (depending on the task), and adding a "view_extra" attribute to each one. view_extra is a dictionary where I generally stick in values that are dependent on things like who is logged in. Apart from being a hassle, it also destroys the laziness of the queryset. I guess I could go so far as to make a generator, but obviously this is not what the Django developers had in mind for us to do.
I should probably try queryset annotation more, but I don't know how well that would work in some more complicated cases. Plus, no good in a tree or list-within-list structure scenario (queryset of items with members that are further querysets I need to iterate over).
I could register a filter, (as suggested here django template system, calling a function inside a model) but that is an abuse of filters, right? They are meant to transform text and maybe data, not to be a specific-purpose replacement for something the developers deliberately tried to get us not to do.
Any "proper" way to do this that I don't know about? Am I off base here by suggesting that this is a deficiency of Django's templating system as it stands?
I don't see why creating a custom tag or filter is an 'abuse'. As far as I'm concerned, that's exactly what they're for, and I use them for that all the time.
Maybe Jinja templates would be a good alternative to using Django's templating system in this instance. Apart from the important fact that Jinja allows you to use some level of logic in your templates, Jinja templates and Django templates are almost identical.
This example code taken directly from the Jinja documents looks like it might be the kind of thing you're trying to achieve.
{% for comment in models.comments.latest(10) %}
...
{% endfor %}
To integrate Jinja with Django, you could look at Coffin

Untrusted templates in Python - what is a safe library to use?

I am building a library that will be used in several Python applications. It get multilingual e-mail templates from an RMDBS, and then variable replacement will be performed on the template in Python before the e-mail is sent.
In addition to variable replacement, I need the template library to support if, elif, and for statements in the templates.
I use Mako for most my projects, and also looked at Tempita as it doesn't provide a lot of features I don't need.
The concern I have is untrusted code execution - can someone point me at a template solution for Python that either does not support code execution, or will allow me to disable it?
From the Django book:
For that reason, it’s impossible to call Python code directly within Django templates. All “programming” is fundamentally limited to the scope of what template tags can do. It is possible to write custom template tags that do arbitrary things, but the out-of-the-box Django template tags intentionally do not allow for arbitrary Python code execution.
Give Django templates a try. It's a little tricky to set up outside of a Django app -- something to do with DJANGO_SETTINGS_MODULE, search around -- but may be trusted.
Have you checked out Jinja2? It's pretty much what you're talking about, and it's a great mix of powerful while keeping things simple and not giving the designer too much power. :)
If you've used Django's template system, it's very similar (if not based off of?) Jinja.

Categories

Resources