Twig cache inside if statement - twig

I'm having following situation where I need to check for global ENV variable (dev || prod)
Using twig v1.x and Timber v1.x
{% if is_prod %}
{% cache 'homepage;#{hash_key};' post %}
{% endif %}
...code
{% if is_prod %}
{% endcache %}
{% endif %}
Fatal error: Uncaught Exception: Unexpected "endif" tag (expecting closing tag for the "cache" tag
Is there a workaround for that. tnx

I think you have two typos here:
{% cache 'homepage;#{hash_key};' post %)
to
{% cache 'homepage;#{hash_key};' post %}
and
{% endcache '%)
to
{% endcache %}

Related

Shopware : Impossible to extend through plugin user-detail

I have Shopware 6.5.3. I was trying to extend "sw-users-permissions-user-detail" like this :
import template from './sw-users-permissions-user-detail.html.twig';
Shopware.Component.override('sw-users-permissions-user-detail', {
template
});
And file 'sw-users-permissions-user-detail.html.twig'
{% block sw_settings_user_detail %}
{% parent %}
{% block test %}
<p>Blabla</p>
{% endblock %}
{% endblock %}
It's not working at all, and I don't know why.
Any help ?
NB : It's working when I'm overriding other templates :
Component.override('sw-dashboard-index', {
template
});
If you want to put the original contents to the block, that you are overriding, you should use the 'parent' statement like this:
{{ parent() }}

Dynamic nav-bar elements - passed from Flask to Jinja - inherited layout template

Environment: Python 3.6, Flask 1.02, Jinja2
Objective:
Create a dynamic menu in layout.html (which is extended by content.html)
yet the url_for of the dynamic element is frequently requires a parameter to be passed
Issue statement:
How can I pass the parameters for url_for in Jinja template when rendering the template?
I feel like I would need the syntax of str().format in Jinja..
I tried to:
1. pass each part as a separate value:
menus = [{'url': 'func_name', 'menu_title': 'title', 'param': 'param_name', 'param_val': 'param_value'}]
return render_template('content1.html', menus=menus]
in jinja I tried to call it like: (I also tried it without the plus and double-quotes)
{{ url_for(func_name), param_name+ "=" + param_val }}
During rendering it gives error of
url_for() takes 1 positional argument but 2 were given
2. tried to use the {% set var_name: passed_variable %}
Built on 1st version of menus defined on server side, I tried to set the variables within Jinja, but also failed.
menus = [{'url': 'func_name', 'menu_title': 'title', 'param': 'param_name', 'param_val': 'param_value'}]
return render_template('content1.html', menus=menus]
Jinja
{% for menu in menus %}
{% set url = menu.get('url') %}
{% set param = menu.get('param') %}
{% set value = menu.get('param_val') %}
{% url_for(url, param + "=" + value %}
Yet it also didn't work.
It feels like if I give a param for the url_for syntax (not a hard-wired string) I cannot add the parameters.
3. tried to pass whole content of url_for as a string:
menus={'url_string': " 'func_name', param_name=param_value"}
yet it fails again as url_for syntacs put the whole between apostrophes, which I wouldn't need at the end.
Some references I scanned through.
Flask context-processor
It could work if I would create another template of each nav-bar for each content page - yet with that move i could simply move the navbar into the content page. However that seems dull. Stack Overflow topic
Thus question:
How can I pass the
param_id=paramval['id']
for the url_for syntax during rendering
{{ url_for('edit_question', param_id=paramval['id']) }}
The code/structure stg like below:
layout.html
<html>
<body>
{% for menu in menus %}
{% for key, value in menu.items() %}
<a href="{{ url_for(value) }}" >
{{ key }}
</a>
{% endfor %}
{% endfor %}
{% block content %}
{% endblock %}
</body>
</html>
content1.html
{% extends 'layout.html' %}
{% block content %}
content
{% endblock %}
content2.html
{% extends 'layout.html' %}
{% block content %}
content
{% endblock %}
app.py
#app.route('/')
def index():
menus = [{'menu_title1': 'menu_func_name1'}]
return render_template('content1.html', menus=menus)
#app.route('/menu_details/<int:menu_nr>')
def show_details_of_menu(menu_nr):
menus = [{'menu_title3': 'menu_func_name3', 'menu_param_name': 'menu_param_value'}
return render_template('content2.html', menus=menus)
sorry for the Wall of text..
sigh.. after hours I just found how to construct the syntax. I hope it will help others!
During rendering:
menus = [{'url': 'func_name', 'menu_title': 'title', 'parameters': {'param1': param1_value}}]
return render_template('context.html', menus=menus]
In Jinja, I adjusted the syntax to manage cases where no parameters are needed:
{% for menu in menus %}
{% if menu.get('parameters').items()|length > 0 %}
<a href="{{ url_for(menu.get('url'), **menu.get('parameters')) }}">
{{ menu.get('menu_title') }}
</a>
{% else %}
<a href="{{ url_for(menu.get('url')) }}">
{{ menu.get('menu_title') }}
</a>
{% endif %}
{% endfor %}

How can I check whether the provided URLs is youtube or vimeo?

I have this two URLs:
https://youtu.be/erwZDijlFAA
https://vimeo.com/262998843
Now i want to check it by Twig. How can i check ?
{% if url %} <p>youtube</p> {% else %} <p>vimeo</p> {% endif %}
Or have any way to check whether the provided URLs is youtube or vimeo ?
You can use a simply version that use starts with operator like:
{% if url starts with 'https://youtu.be/' %}
YouTube.com
{% endif %}
Or for more complex criteria you can use Regular expression thru matches like:
{% if url matches '%(?:youtube(?:-nocookie)?\.com/(?:[^/]+/.+/|(?:v|e(?:mbed)?)/|.*[?&]v=)|youtu\.be/)([^"&?/ ]{11})%i' %}
YouTube.com
{% endif %}
RegEx credits: https://gist.github.com/ghalusa/6c7f3a00fd2383e5ef33
More info in the doc about comparison operator here
Hope this help
You can use the below code to segregate the videos in twig.
{% set link_type = view.field.body.original_value %} // Fetching value from the body field
{% if ('youtube' in link_type|render|render) %}
youtube url
{% else if ('vimeo' in link_typr|render|render ) %}
vimeo Url
{% endif %}

django-sitetree sitetree_items always empty

I've set up the tree using the GUI.
This works well:
{% load sitetree %}
{% sitetree_menu from "mainmenu" include "trunk" %}
This does NOT:
{% load sitetree %}
{% for item in sitetree_items %}
ITEM: {{ item.title_resolved }}<br/>
{% endfor %}
The for loop generates nothing.
What am I doing wrong here?
Versions:
django-sitetree 1.9.0
python 3.5.2
django 2.0
tree admin screenshot

Symfony & Twig: how to get vars in twig by DB data?

One question please.
{{ dump(app.user.slugName) }}
If I do the above snippet in Twig, I get the slugName of the user loged ("my-user-2", i.e.) in the app (SlugName is an atribute of the entity user). Ok & Correct. But... I want to order this action from a var (var from BD data)
I have a variable named option which is set like this:
{% set option = 'app.user.slugName' %}
But when I'm trying output this variable with {{ dump(option)}} it returns app.user.slugName as literal. It does not return my-user-2.
Is there are any way in twig to solve this? It's a function to generate a menu, but some links needs some parameters.
I see what you mean, but Twig can't evaluate expression like that.
To achieve something like that you would need a snippet like this,
{% set value_methods = 'app.user.slugname' %}
{% set option_value = _context %}
{% for method in (value_methods|split('.')) if method != '' %}
{% set option_value = attribute(option_value, (method|replace({'()': '', }))) %}
{% endfor %}
{{ option_value }}
twigfiddle
(edit)
Remember you can create a macro to achieve some reusability for this snippet,
{% import _self as macros %}
{{ macros.evaluate(_context, 'app.user.slugname') }}
{% macro evaluate(context, value_methods) %}
{% set option_value = context %}
{% for method in (value_methods|split('.')) if method != '' %}
{% set option_value = attribute(option_value, (method|replace({'()': '', }))) %}
{% endfor %}
{{ option_value }}
{% endmacro %}

Resources