Use array in a Django template file - django-templates

I know that in a template you can use for statement in an HTML file.
e.g.:
{% for item in array %}
<!-- do something -->
{% endfor %}
Is there a way to access an array in a template without using a for loop? Like {{values[0}}?
I am using Python and Django.

You can access the variables from the list using indexing.
{{ array.0 }}

Related

How to use expressions in if statements in DBT

I want to know how, if possible, I can use dbt expressions that are enclosed in two curly brackets ({{ }}), inside a statement that is enclosed in a curly bracket and a percent sign ({% %}).
For example, I want to execute a piece of code in DBT if the table exists. In my head, it would look something like:
{% if {{this}} is not none %}
do something
{% endif %}
But there's a syntax issue here and I can't seem to be able to use expressions inside statement blocks. I have seen the following implementation but I want to know how I can replace source with {{this}}.
{% set table_exists=source('db', 'table') is not none %}
{% if table_exists %}
do something
{% endif %}
These are the docs I have read:
'this' jinja function
jinja and macros
dbt if table exists example
using load_relation to check if model exists
Don't Nest Your Curlies
If you're inside either {{ ... }} or {% ... %}, your code will be executed by the jinja templating engine. this is a variable that is already set in the jinja context. You use {{ this }} in SQL, but if you're already in the jinja context provided by {% ... %}, you can just write this, without the curlies.
Your if block becomes:
{% if this is not none %}
do something
{% endif %}

Cycle inside render tag

I am looping through products and I need the cycle tag based on loop.
{% for product in collection.products %}
{% render 'product-grid-item', product: product %}
{% endfor %}
Inside the "product-grid-item", I have:
{% assign class_1 = 'small-6 medium-4' %}
{% assign class_2 = 'small-6 medium-3' %}
{% capture grid_item_width %}
{% cycle class_1, class_1, class_1, class_2, class_2, class_2, class_2 %}
{% endcapture %}
The cycle is not working, because it is not directly inside the "for loop". Any idea how to get this working?
I am aware of alternatives, I am just trying to make "cycle" work inside a render tag.
Render is a closed piece of code, it can't read what is happening outside of it.
So at the moment you not only don't have access to the cycle but you don't have access to the forloop object as well.
You are looking for how the include works but that is deprecated and you shouldn't use it.
So the short answer is you can't make it work, since the main logic of the render is to work this way.
The only way to make the render aware of something outside it is to pass a variable to it, so you need to make your cycle logic outside of it and pass the resulting variable inside of it.
What you are trying to do is possible as long as you rearrange your approach slightly. You will just need to do your math outside of the snippet and pass an appropriate value as a variable into the snippet.
{% assign class_array = 'class-1,class-1,class-1,class-2,class-2,class-2,class-2' | split: ',' %}
{% for product in collection.products %}
{% assign loop_position = forloop.index0 | modulo: class_array.size %}
{% render 'product-grid-item', product: product, class_name: class_array[loop_position] %}
{% endfor %}
How this works
Just like before, we make a comma-separated array of class names that we want to cycle through. (We cannot make an array directly, but we can turn a delimited string into an array pretty easily using the split filter) - but this time we assign that to a variable.
We then use the forloop index and the modulo operator to get a value between 0 and the last index position of our array list and use that number as the lookup value for our array. That value is passed into the rendered snippet so that product-grid-item can access it.
If we ever need to change our cycling class names, all we have to do is update the array with the new values. Even if the number of values changes in the future, the code will still work to cycle through all of the values provided.
Cheers!

Jinja / Django for loop range not working

I'm building a django template to duplicate images based on an argument passed from the view; the template then uses Jinja2 in a for loop to duplicate the image.
BUT, I can only get this to work by passing a list I make in the view. If I try to use the jinja range, I get an error ("Could not parse the remainder: ...").
Reading this link, I swear I'm using the right syntax.
template
{% for i in range(variable) %}
<img src=...>
{% endfor %}
I checked the variable I was passing in; it's type int. Heck, I even tried to get rid of the variable (for testing) and tried using a hard-coded number:
{% for i in range(5) %}
<img src=...>
{% endfor %}
I get the following error:
Could not parse the remainder: '(5)' from 'range(5)'
If I pass to the template a list in the arguments dictionary (and use the list in place of the range statement), it works; the image is repeated however many times I want.
What am I missing? The docs on Jinja (for loop and range) and the previous link all tell me that this should work with range and a variable.
Soooo.... based on Franndy's comment that this isn't automatically supported by Django, and following their link, which leads to this link, I found how to write your own filter.
Inside views.py:
from django.template.defaulttags import register
#register.filter
def get_range(value):
return range(value)
Then, inside template:
{% for i in variable|get_range %}
<img src=...>
{% endfor %}

How to fetch product metafields in cart.js Shopify

How do I get product meta fields in Shopify store cart.js response?
Currently, In cart.js not providing any details of product metafields.
You have many possible hack.
The one I would recommend if you are using CartJS is
In your product page, print the product metafield in the HTML
<div class="product-page" data-metafield="{{product.metafield.namespace.value}}">
</div>
When product is added, simply add the metafield as a line item property
var properties = {metafield : $('.product-page').data('metafield')};
CartJS.addItem(variantId, 1 ,properties);
The metafield is now accessible at CartJS.cart.items[i].properties[metafield] !
** You can do this by adding the following step**
Add the below code in product form
{% for field in product.metafields.namespace%}
<input required class="required hidden" id="customID" type="hidden" value='{{ field | last }}' name="properties[metafields[{{ field | first }}]]">
{% endfor %}
it will add in your cart object you can access it by
{% for field in item.properties.metafields %}
{{ field | first }}: {{ field | last }}
{% endfor %}
Metafields are available client-side via Liquid. You do not need cartJS to fetch them. You can render the product metafields of interest into your own data structure of choice, and use the as you wish anyway you want.
You could also build out a StorefrontAPI based system and try GraphQL if you're really keen.
You can access the metafield using item.product.metafields.your-namespace.your-key.
You can get the metafields content of the appropriate products, collections, orders by assigning it to a variable in the liquid file.
In the product-template.liquid, you can use
{% assign var_meta = page.metafields.meta_namespace %}
// You can use the Shopify docs to understand how you create Metafields
{% assign key = 'meta_key' %}
{% assign key_val_meta = meta_namespace.meta_key %}
Access the variable
{{key_val_meta}}
If you assign unique values to the metafield, you could use it to get the exact information you can input that information in your cart.js function.
{%- if item.product.metafields.my_fields.minimum_order_quantity != blank -%}
{{ item.product.metafields.my_fields.minimum_order_quantity }}
{%- endif -%}
Use this code and show data on cart page

Variable within liquid if statement when calling shopify settings

I thought this would be simple to solve but I am trying to put a variable within a liquid statement.
I have my variable {{ loop_index }} and I want it to be within this statement :
{% if settings.dropdown-[loop_index]-select %}
I tried putting [...] round it but that didn't work. Basically it should say settings.dropdown-1-select, settings.dropdown-2-select.
What am I doing wrong?
Create a string containing the variable name, then use the square bracket notation to access the setting with that name. For example:
{% capture var %}dropdown-{{ loop_index }}-select{% endcapture %}
{% if settings[var] %}