Jinja 2 : escaping and extending - django-templates

I am trying to output html after running my templates through Jinja2 and thereafter through Django. The {{ 'RAW' }} and {% raw %}...{% endraw %} tags are not doing what I expect then to and there is not a lot of documentation on this nor does my googling yield anything helpful.
As an example consider the following series of templates. The first is a stock Jinja2 base page which one wants to extend.
{# jinja_base.html #}
{% block jinja_head %}
JINJA HEAD
{% endblock jinja_head %}
{% block jinja_body %}
JINJA BODY
{% endblock jinja_body %}
{% block jinja_foot %}
JINJA FOOT
{% endblock jinja_foot %}
The second is a stock Django template page that one wants to extend.
{# django_base.html #}
{% block django_head %}
DJANGO HEAD
{% endblock django_head %}
{% block django_body %}
DJANGO BODY
{% endblock django_body %}
{% block django_foot %}
DJANGO FOOT
{% endblock django_foot %}
To extend both of them I have a Jinja/Django mixin template that reads as follows. The idea is to run it through Jinja first then through Django.
{# mixin.html #}
{{ '{% extends "django_base.html" %}' }}
{% extends "jinja_base.html" %}
{{ '{% block django_head %}' }}
{% block jinja_head %}
MIXIN HEAD
{% endblock jinja_head %}
{{ '{% endblock django_head %}' }}
{{ '{% block django_body %}' }}
{% block jinja_body %}
MIXIN BODY
{% endblock jinja_body %}
{{ '{% endblock django_body %}' }}
{{ '{% block django_foot %}' }}
{% block jinja_foot %}
JINJA FOOT
{% endblock jinja_foot %}
{{ '{% endblock django_foot %}' }}
After the Jinja run, I'm expecting the following output
{% extends "django_base.html" %}
{% block django_head %}
MIXIN HEAD
{% endblock django_head %}
{% block django_body %}
MIXIN BODY
{% endblock django_body %}
{% block django_foot %}
JINJA FOOT
{% endblock django_foot %}
however, I am getting the following instead.
{% extends "jinja_base.html" %}
MIXIN HEAD
MIXIN BODY
JINJA FOOT
That is all the Django code which is embedded in the Jinja escape sequences is getting stripped. The first tag however is retained.
The docs mention that anything before an extends is kept as is but that everything after is not. There is no explanation on how best to circumvent this nor why this affects raw/escaped code.
Hmm.. perhaps I must place the extends right at the end ?

After you extend a template you have to put the content between blocks. Every other stuff is ignored. So in the mixin.html:
{{ '{% block django_head %}' }} <--- ignored
{% block jinja_head %}
MIXIN HEAD
{% endblock jinja_head %}
{{ '{% endblock django_head %}' }} <--- ignored
The first and the last line are outside of the jinja_head block, thus will be ignored.
The correct way is straightforward, just put the Django lines between Jinja's blocks, e.g.:
{% block jinja_head %}
{{ '{% block django_head %}' }}
MIXIN HEAD
{{ '{% endblock django_head %}' }}
{% endblock jinja_head %}
This results:
{% block django_head %}
MIXIN HEAD
{% endblock django_head %}
For the {{ '{% extends "django_base.html" %}' }} just define an empty block in jinja_base.html, which you can override in the mixin.html with the Django extends line. The complete example:
jinja_base.html
{# jinja_base.html #}
{% block django_extends %}
{% endblock django_extends %}
{% block jinja_head %}
JINJA HEAD
{% endblock jinja_head %}
{% block jinja_body %}
JINJA BODY
{% endblock jinja_body %}
{% block jinja_foot %}
JINJA FOOT
{% endblock jinja_foot %}
mixin.html
{# mixin.html #}
{% extends "jinja_base.html" %}
{% block django_extends %}
{{ '{% extends "django_base.html" %}' }}
{% endblock django_extends %}
{% block jinja_head %}
{{ '{% block django_head %}' }}
MIXIN HEAD
{{ '{% endblock django_head %}' }}
{% endblock jinja_head %}
{% block jinja_body %}
{{ '{% block django_body %}' }}
MIXIN BODY
{{ '{% endblock django_body %}' }}
{% endblock jinja_body %}
{% block jinja_foot %}
{{ '{% block django_foot %}' }}
JINJA FOOT
{{ '{% endblock django_foot %}' }}
{% endblock jinja_foot %}
This way you will see the expected result after Jinja's render:
{% extends "django_base.html" %}
{% block django_head %}
MIXIN HEAD
{% endblock django_head %}
{% block django_body %}
MIXIN BODY
{% endblock django_body %}
{% block django_foot %}
JINJA FOOT
{% endblock django_foot %}

Related

How to get all tags of all collections products with tag link

I need to fetch all the tags on my collection page and display it within tag link.
I use this below code :
{% assign collection = collections.all %}
{% paginate collection.products by 1000 %}
<h3>All Tags</h3>
<div id="tags">
{% if collection.tags.size == 0 %}
No tags found.{% else %}
{% for tag in collection.tags %}
<a href="{{ collection.url }}/{{ tag | handle }}">
{{ tag }}
</a>
{% unless forloop.last %}, {% endunless %}
{% endfor %}
{% endif %}
</div>
{% endpaginate %}
Please help me to solve my problem.
I think you need to use a built-in solution rather than paginate
use like it
<h3>All Tags</h3>
<div id="tags">
{% if collection.all_tags.size == 0 %}
No tags found.
{% else %}
{% for tag in collection.all_tags %}
{{ tag | link_to_tag: tag }}
{% unless forloop.last %}, {% endunless %}
{% endfor %}
{% endif %}
</div>
please replace below code :
{{ tag }}
To this :
{{ tag | link_to_tag: tag }}

Is there any way to get settings value of another snippet in shopify?

I have made a block and snippet files for each item in the block.```
{% for block in section.blocks %}
<div {{ block.shopify_attributes }}>
{% case block.type %}
{% when 'cart_header' %}
{% include 'cart_header' %}
{% when 'Countdown_Timer' %}
{% include 'Countdown_Timer' %}
{% when 'Announcement_Bar' %}
{% include 'Announcement_Bar' %}
{% when 'Free_Shipping_Bar' %}
{% include 'Free_Shipping_Bar'%}
{% endcase %}
</div>
{% endfor %}```
Is there any way or trick that I can get block.settings.xxx value of cart_header on countdown_timer snippet file?

Hiding products based on customer tag Shopify search.liquid

I hope someone may be able to help with this.
I am currently setting up my store with shopify and have duplicated my products for retail and wholesale customers.
The only issue I am faced with is that the retail products are still showing when a customer with the 'wholesale' tag uses the search box.
I was wondering if I add a 'retail' tag to the relevant products, can add any code in search.liquid so that if the customer.tag contains 'wholesale' do not show products with product.tags 'retail' or something along those lines?
My current search.liquid looks like:
<!-- /templates/search.liquid -->
{% comment %}
To return only products or pages in results:
- http://docs.shopify.com/manual/configuration/store-customization/return-only-product-in-storefront-search-results
- Or manually add type=product or type=page to the search URL as a parameter
{% endcomment %}
{% comment %}
Check to enforce respond.js
{% endcomment %}
{% assign respond_js_secret_key = shop.domain | md5 %}
{% unless search.terms == respond_js_secret_key %}
{% comment %}
Avoid accessing search.results before the opening paginate tag.
If you do, the pagination of results will be broken.
{% endcomment %}
{% paginate search.results by 12 %}
<div class="grid">
<div class="grid__item">
<header class="section-header text-center">
{% if search.performed %}
{% if search.results_count == 0 %}
<h1 class="text-center">{{ 'general.search.no_results_html' | t: terms: search.terms }}</h1>
{% else %}
<h1 class="text-center">{{ 'general.search.results_for_html' | t: terms: search.terms }}</h1>
{% endif %}
{% else %}
<h1 class="text-center">{{ 'general.search.title' | t }}</h1>
{% endif %}
<hr class="hr--small">
</header>
{% include 'search-bar', search_btn_style: 'btn', search_bar_location: 'search-bar--page' %}
{% if search.performed %}
<hr class="hr--medium hr--clear">
<div class="grid-uniform">
{% for item in search.results %}
{% assign itemIswholesale = false %}
{% if item.tags contains 'wholesale' or item.title contains 'wholesale' %}
{% assign itemIswholesale = true %}
{% endif %}
{% if itemIswholesale and customer and customer.tags contains 'wholesale' %}
{% if item.object_type == 'product' %}
{% assign product = item %}
{% include 'product-grid-item' %}
{% else %}
<div>
<div>
<a href="{{ item.url }}">
<span>
<span>{{ item.title }}</span>
{{ item.content | strip_html | truncatewords: 60 }}
</span>
</a>
</div>
</div>
{% endif %}
{% else %}
{% unless itemIswholesale %}
{% if item.object_type == 'product' %}
{% assign product = item %}
{% include 'product-grid-item' %}
{% else %}
<div>
<div>
<a href="{{ item.url }}">
<span>
<span>{{ item.title }}</span>
{{ item.content | strip_html | truncatewords: 60 }}
</span>
</a>
</div>
</div>
{% endif %}
{% endunless %}
{% endif %}
{% endfor %}
</div>
{% if paginate.pages > 1 %}
{% include 'pagination' %}
{% endif %}
{% endif %}
</div>
</div>
{% endpaginate %}
{% else %}
{% include 'respond' %}
{% layout none %}
{% endunless %}
I am a complete novice and have managed to get by this far following help and tutorials online so any help would be very much appreciated.
I can't afford to subscribe to an additional app at present, such as locksmith and would really like to keep control so I can continue administration in future,
Thanks in advance,
You may try doing something like that inside the
{% if search.performed %}
condition.
First get some information about user and store it:
{% assign wholesale = false %}
{% if customer %}
{% assign customer_tags = customer.tags | split: "," %}
{% if customer_tags contains 'wholesale' %}
{% assign wholesale = true %}
{% endif %}
{% endif %}
Explanations : first you assign a false statement to the wholesale status. Then you check if it is customer ( no need to go further if user is not connected). If he is, then you check if he has a wholesale tag. If he is you assign a true statement.
Then you are able to display something different this way:
{% for result in search.results %}
{% if wholesale %}
Do something
{% else %}
Do something else
{% endif %}
{% endfor %}
Please not that you may have some issues with pagination.

Include a snippet with raw content in Shopify

I need a way to so something like this.
{% raw %}
{% include "snippet" %}
{% endraw %}
Except this prevents include from running. So it doesn't do what I need.
Ideally there was a include_raw tag.
Update:
The following:
<!-- reggi 090 -->
<script type="text/liquid">
{% capture raw_data %}{% include 'product_thumbnail' %}{% endcapture %}
{% raw %}{{ raw_data }}{% endraw %}
</script>
Simply renders to:
<!-- reggi 090 -->
<script type="text/liquid">
{{ raw_data }}
</script>
Try this
{% capture raw_data %}{% include 'snippet' %}{% endcapture %}
{% raw %}}{{ raw_data }}{% endraw %}

shopify Liquid error: Memory limits exceeded

I was trying to display all the product types of my site in one page , 2 days back it was listing all the all the product type.
But now when that page is loads its giving error like "shopify Liquid error: Memory limits exceeded"
Here is my code
<div class="rte">
{{ page.content }}
<ul class="vendor-list block-grid three-up mobile one-up">
{% for product_type in shop.types %}
{% assign its_a_match = false %}
{% capture my_collection_handle %} {{ type | handleize | strip | escape }} {% endcapture %}
{% assign my_collection_handle_stripped = my_collection_handle | strip | escape %}
{% for collection in collections %}
{% if my_collection_handle_stripped == collection.handle %}
{% assign its_a_match = true %}
{% endif %}
{% endfor %}
{% if its_a_match %}
<li class="vendor-list-item">{{ product_type }}</li>
{% endif %}
{% endfor %}
</ul>
</div>
how can i overcome this problem ?
Try the following. It's faster and more efficient.
<div class="rte">
{{ page.content }}
<ul class="vendor-list block-grid three-up mobile one-up">
{% for product_type in shop.types %}
{% assign type = product_type | strip | escape | handleize %}
{% assign collection = collections[type] %}
{% if collection.handle != '' %}
<li class="vendor-list-item">{{ product_type }}</li>
{% endif %}
{% endfor %}
</ul>
</div>