I have two blocks that call the same method with same variables. I want to call the method only once, but the result is then outsite the scope of the block tags. I've tried calling this method in the parent template header.html
and with a with
tag, but nothing seems to work.
This is the layout:
{% extends "header.html" %}
{% load navigation_tags %}
{% block header %}
{% get_section site=site as section %}
{% include "foobar.html" with section=section %}
{% endblock header %}
{% block navigation %}
<nav>
<div class="container">
{% get_section site=site as section %}
{% navigation section.slug %}
</div>
</nav>
{% endblock navigation %}
navigation_tags.py
@register.assignment_tag
def get_parent_section(site):
if site.id == settings.FOOBAR_SITE_ID:
section = Section.objects.get(id=settings.FOOBAR_SECTION_ID)
else:
# This is also a section instance.
return site.default_section
2 Answers 2
As mentioned by 2pacho in another answer and Fernando Cezar in a comment, the easiest way to share values between different sections is to set it in the template context. If you are using the render shortcut function, you can pass a dict
as the context parameter to add a value to the rendering context of the template. That would be a good place to add it and this would be the easiest place to put it.
return render(request, 'template.html', {'section': get_parent_section(site)})
However, if for some reason, you can't include it in the context, you can use a decorator to add memoization to your function, so that it will cache the computation results and return it immediately when called with the same parameters. You can use functools.lru_cache
to do so, or it's Django backport at django.utils.lru_cache.lru_cache
if you are using Python 2.x.
@register.assignment_tag
@functools.lru_cache()
def get_parent_section(site):
if site.id == settings.FOOBAR_SITE_ID:
section = Section.objects.get(id=settings.FOOBAR_SECTION_ID)
else:
# This is also a section instance.
return site.default_section
2 Comments
I wouldn't call a method outside .py . Think that this is using Jinja2 templates, it's powerful but not in the way that the backend can be.
What I recommend you doing in this case is to generate a context for the template and use this variables there.
Would be as simple as adding it to your context where it's being generated.
context['site_parent'] = get_parent_section(site)
Think that Jinja2 (html) has to be as simple as possible and that can help you with basic coding and time saving (like loops to print the exact same information or show and hide code depending on the context) but I would keep it as simple you can when rendering.
If you would like you can read official django website about templates https://docs.djangoproject.com/en/2.0/topics/templates/
But from my expirience I would keep the method calls in the views.py
get_section
as well.... Also if it isn't an expensive call it might be easier to just do it twiceif
condition?section
info in the context being injected there by the view?