jinja2.exceptions.UndefinedError: list object has no element 1 - json

"artists": {
"href": "https://api.spotify.com/v1/search?query=Hozier&type=artist&offset=0&limit=20",
"items": [
{
"images": [
{
"height": 640,
"url": "https://i.scdn.co/image/2e4114631a20bd71903bc335b88f872afdce9a33",
"width": 640
},
{
"height": 320,
"url": "https://i.scdn.co/image/4d4be818dc98d47b9086ecff8ec4883902781070",
"width": 320
},
{
"height": 160,
"url": "https://i.scdn.co/image/c181b6184e82bd7f8411d97b87e4f1daa1bbbbb8",
"width": 160
}
]
}
]
}
I'm trying to access the value of the url key in the second dict using jinja2, the problem is that every time i run the webpage it gives me a status code 500 and upon closer look in the terminal it gives me a jinja2.exceptions.UndefinedError: list object has no element 1 but that doesn't make sense to me since it prints {{value[1]}} just fine. The issue arises when i try to loop through the keys and values of that dict.
The following is my jinja2 code. if you can point out what i'm doing wrong or what i'm missing here that would be truly appreciated.
{% if q_type == "artist" %}
{% for record in results['artists']['items'] %}
{% for key, value in record.items() %}
{% if key == "images" %}
{% for k, v in value[1].items() %}
{% if k == "url" %}
{{info.append(v) or ""}}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endfor %}
{% endif %}

Related

json_decode a nested array/object

I have received a JSON payload for an order / abandon cart in this format.
{
"tokens": {
"locale": "en_GB",
"currency": "EUR",
"entity_id": "36140",
"item[0].type": "straw",
"item[0].row_total_incl_tax": "2000.0000",
"item[0].quantity": "2.0000",
"item[0].name": "Diego",
"item[0].straw_type": "itri",
"item[0].mot": "20",
"item[1].type": "virtual",
"item[1].row_total_incl_tax": "625.0000",
"item[1].quantity": "1.0000",
"item[1].name": "Mixmatch",
"item[2].type": "straw",
"item[2].row_total_incl_tax": "1000.0000",
"item[2].quantity": "1.0000",
"item[2].name": "Diego",
"item[2].straw_type": "abc",
"item[2].mot": "20",
"item[3].type": "straw",
"item[3].row_total_incl_tax": "600.0000",
"item[3].quantity": "1.0000",
"item[3].name": "Pete",
"item[3].straw_type": "itri",
"item[3].mot": "20"
}
}
I can print values like tokens.entity_id - this works successfully.
However, for each of the Items e.g. item[0] I want to pull the item.name to print using Twig and can't seem to make this work.
I have tried several things e.g.
{% set cart = contact.json_field | json_decode %}
{% for tokens in cart %}
Entity : {{tokens.entity_id | raw }} <br>
{% for item in tokens %}
Item Name : {{item.name | raw }} <br>
{% endfor %}
{% endfor %}
I have also tried tokens.item.name, and tokens.item1.name, and tokens.item[1].name but never seems to be able to pull the values for the items.
Any help would be appreciated as I'm new to Twig
Managed to resolve this, by restructuring the json data
<ul>
Item Name : {{tokens.entity_id | raw }}
{% set count = 0 %}
{% for item in tokens.items %}
{% set counter = ( counter | default(0) ) + 1 %}
{% set test = tokens.items.1.type %}
{{counter}}
Item Name : {{tokens.items.1.type | raw }}
Item Name : {{tokens.items.1.row_total_incl_tax | raw }}
{% endfor %}
</ul>
json
"link_order_status": "http://testing.com/en/",
"items": {
"0": {
"type": "straw",
"row_total_incl_tax": "400.0000"
},
"1": {
"type": "testing #1",
"row_total_incl_tax": "300.0000"
},
"2": {
"type": "testing #2",
"row_total_incl_tax": "200.0000"
}
}

Get loop index of outer loop and end with comma

In jinja2, I have a loop inside another loop and I want to write a comma if not last loop.
This is what I have so far:
// ksp = "{'a': ['someString', ['someString'], ['a1', 'a2']], 'b': ['someString', ['someString'], ['b1', 'b2', 'b3']]}"
"users": {
{% for kvd in ksp %}
{% set outer_loop = loop %}
{% for kvt in ksp[kvd][2] %}
"{{ kvt }}": {
"username": "{{ ksp[kvd][1][0] }}"
}{% if not outer_loop.last %},{% endif %}{% endfor %}{{ '' }}{% endfor %}
},
This is what I'm getting:
"users": {
"a1": {
"username": "someString"
},
"a2": {
"username": "someString"
},
"b1": {
"username": "someString"
}
"b2": {
"username": "someString"
}
"b3": {
"username": "someString"
}
}
As you can see, it's missing commas in the last three because they belong to the last outer_loop.index and because of that, it's not a valid JSON. How can I solve this?
Working now, it was just a matter of changing the "if" condition to:
{% if not (outer_loop.last and loop.last) %},{% endif %}{% endfor %}{{ '' }}{% endfor %}

Failed to extract value from json output

I am trying to extract the value of snapshot_policy_schedules.snapshot_schedule_info from the below list:
[
{
'enabled': 'true',
'policy': 'default-DR',
'policy_owner': 'vserver-admin',
'snapshot_policy_schedules': {
'snapshot_schedule_info': [
{
'count': '6',
'prefix': 'hourly',
'schedule': 'hourly',
'snapmirror_label': '-'
},
{
'count': '2',
'prefix': 'daily',
'schedule': 'daily',
'snapmirror_label': 'daily'
},
{
'count': '2',
'prefix': 'weekly',
'schedule': 'weekly',
'snapmirror_label': 'weekly'
}
]
},
'total_schedules': '3',
'vserver_name': 'net'
}
]
However I am getting the error:
fatal: [localhost]: FAILED! => {"changed": false, "msg": "AnsibleUndefinedVariable: 'list object' has no attribute 'snapshot_policy_schedules'"}
This is my code:
{% for schedule in policy.snapshot_policy_schedules.snapshot_schedule_info %}
{% if schedule.schedule == 'weekly' %}
{% set policy_weekly = schedule.count %}
{% endif %}
{% if schedule.schedule == 'daily' %}
{% set policy_daily = schedule.count %}
{% endif %}
{% if schedule.schedule == 'hourly' %}
{% set policy_hourly = schedule.count %}
{% endif %}
{% endfor %}
Q: "'list object' has no attribute 'snapshot_policy_schedules'"
A: The 'list object' i.e. the variable policy is a list. You probably want to address the first element
{% for schedule in policy.0.snapshot_policy_schedules.snapshot_schedule_info %}
For example, simplified JSON
{
"policy": [{
"schedules": {
"info": [
{"count": "6","prefix": "hourly"},
{"count": "2","prefix": "daily"},
{"count": "2","prefix": "weekly"}]
}
}]
}
and simplified Jinja
- debug:
msg: |-
{% for item in policy.0.schedules.info %}
{{ item.count }} {{ item.prefix }}
{% endfor %}
give
msg: |-
6 hourly
2 daily
2 weekly
Another solution to get the first element of a sequence is to use the first filter of Jinja:
{% for schedule in (policy | first).snapshot_policy_schedules.snapshot_schedule_info %}

Removing an image for Desktop users and not for Mobile users

On my shopify store i want to disable the "collection-image" for the desktop users and not for mobile users, since i'am not 'expert with codes" i mess up everytime i try to change soemthing the reason why i want to disable this it's simple on desktop it looks horribly while on the phone it looks perfect so i'am here asking for your help
{% if section.blocks.size > 0 %}
{%- assign enable_sidebar = true -%}
{% else %}
{%- assign enable_sidebar = false -%}
{% endif %}
{%- assign products_per_page = section.settings.products_per_page_range -%}
{% if section.settings.image_placement != 'default' and section.settings.image_placement != 'hidden' and collection.image %}
<div class="hero-content header {{ section.settings.image_placement }}">
{%- assign image = collection.image -%}
<div class="collection-image" {% if section.settings.image_placement == 'above' %}style="max-width:{{ image.width }}px;"{% endif %}>
<div class="card__image-wrapper" style="padding-top:{{ 1 | divided_by: image.aspect_ratio | times:100}}%">
{% assign image_widths = '295,394,590,700,900,1200,1500,1800,2000,2400' %}
{% include 'theme-rias' %}
<img class="card__image lazyload"
src="{{ image | img_url: '590x' }}"
data-src="{{ image_url_pattern }}"
data-widths="[{{ image_widths }}]"
data-aspectratio="{{ image.aspect_ratio }}"
data-sizes="auto"
alt="{{ image.alt | escape }}">
<noscript>
<img class="card__image" src="{{ image | img_url: '1200x' }}" alt="{{ image.alt | escape }}">
</noscript>
</div>
</div>
</div>
{% endif %}
{% paginate collection.products by products_per_page %}
<section class="collection" data-section-id="{{ section.id }}" data-section-type="collection-template">
<div class="wrapper">
<header class="content-util">
{% include 'breadcrumb' %}
{% include 'social-icons' %}
</header>
<div class="grid {% unless enable_sidebar %}full-width{% endunless %}">
<div class="collection-container">
<header class="collection-header">
<div class="container">
<h1>{{ collection.title }}</h1>
{% include 'collection-sorting' %}
</div>
{% if section.settings.image_placement == 'default' and collection.image %}
<div class="collection-image">
{%- assign image = collection.image -%}
<div class="card__image-wrapper" style="padding-top:{{ 1 | divided_by: image.aspect_ratio | times: 100}}%">
{% assign image_widths = '295,394,590,700,900,1200,1500,1800,2000,2400' %}
{% include 'theme-rias' %}
<img class="card__image lazyload"
src="{{ image | img_url: '590x' }}"
data-src="{{ image_url_pattern }}"
data-widths="[{{ image_widths }}]"
data-aspectratio="{{ image.aspect_ratio }}"
data-sizes="auto"
style="width:{{ image.width }}px;"
alt="{{ image.alt | escape }}">
<noscript>
<img class="card__image" src="{{ image | img_url: '1200x' }}" alt="{{ image.alt | escape }}">
</noscript>
</div>
</div>
{% endif %}
{% if collection.description != blank %}
<div class="description rte">
{{ collection.description }}
</div>
{% endif %}
</header>
{% if enable_sidebar %}
<div class="mobile-aside-container">
{{ 'layout.navigation.collection_menu' | t}}
<aside>
{% include 'collection-sidebar' %}
</aside>
</div>
{% endif %}
<div class="products products-grid {% unless enable_sidebar %}full-width{% endunless %}">
{% comment %}
Loop through our products in the current collection.
See the snippet 'product-grid-item' for the layout.
{% endcomment %}
{% for product in collection.products %}
{% include 'product-grid-item' %}
{% else %}
{% if collection.handle == 'all' and collection.all_vendors.size == 0 and collection.all_types.size == 0 %}
{% for i in (1..products_per_page) %}
{% include 'placeholder-product-grid-item' %}
{% endfor %}
{% else %}
{% comment %}
If collection exists but is empty, display message
{% endcomment %}
<p>{{ 'collections.general.no_matches' | t }}</p>
{% endif %}
{% endfor %}
</div>
{% if paginate.pages > 1 %}
<footer class="collection-footer">
{% include 'pagination' %}
</footer>
{% endif %}
</div>
{% if enable_sidebar %}
<div class="aside-container">
<aside>
{% include 'collection-sidebar' %}
</aside>
</div>
{% endif %}
</div>
</div>
</section>
{% endpaginate %}
{% schema %}
{
"name": "Collection pages",
"settings": [
{
"type": "range",
"id": "products_per_page_range",
"label": "Number of products on each page",
"min": 12,
"max": 48,
"step": 12,
"default": 12
},
{
"type": "select",
"id": "image_placement",
"label": "Collection image placement",
"options": [
{ "value": "default", "label": "After collection title" },
{ "value": "above", "label": "After navigation" },
{ "value": "above-full", "label": "After navigation full width" },
{ "value": "hidden", "label": "Hidden" }
],
"default": "default"
},
{
"type": "checkbox",
"id": "sort_enable",
"label": "Enable sorting",
"default": true
},
{
"type": "checkbox",
"id": "layout_enable",
"label": "Enable grid and list views",
"default": true
}
],
"blocks": [
{
"type": "menu",
"name": "Sidebar menu",
"settings": [
{
"type": "link_list",
"id": "linklist",
"label": "Menu",
"default": "main-menu"
}
]
},
{
"type": "tags",
"name": "Sidebar tags",
"limit": 1,
"settings": [
{
"type": "text",
"id": "title",
"label": "Heading",
"default": "Shop by"
},
{
"type": "radio",
"id": "tag_style",
"label": "Show tags as",
"options": [
{ "value": "buttons", "label": "Buttons" },
{ "value": "menu", "label": "Menu" }
],
"default": "buttons"
},
{
"type": "checkbox",
"id": "tag_grouping",
"label": "Enable tag grouping",
"default": false,
"info": "[Learn how to set up tag groups](http://help.stylehatch.com/article/289-collections)"
}
]
}
]
}
{% endschema %}

Autocomplete popup automatically displaying in only one type of file. In others, it only displays when you hit the tab key

I've created this autocomplete file, and it works:
{
"scope": "source, text",
"completions":
[
{ "trigger": "load: {% load ... %}", "contents": "{% load ${1:static} %}$0" },
{ "trigger": "call: {% ... %} (call)", "contents": "{% $1 %}$0" },
{ "trigger": "comment: {% comment %}...{% endcomment%}", "contents": "{% comment %}\n\t$0\n{% endcomment %}\n" },
{ "trigger": "lcm: {# ... #} (line comment)", "contents": "{# $0 #}" },
{ "trigger": "if: {% if %}...{% endif %} ", "contents": "{% if $1 %}\n\t$0\n{% endif %}\n" },
{ "trigger": "ife: {% if %}...{% else %}...{% endif %}", "contents": "{% if $1 %}$2{% else %}$3{% endif %}$0" },
{ "trigger": "ife: {% if %}\\n...\\n{% else %}...{% endif %}", "contents": "{% if $1 %}\n\t$0\n{% else %}\n{% endif %}\n" },
{ "trigger": "url: {% url '...' %}", "contents": "{% url '$1' %}$0" },
{ "trigger": "extends: {% extends '...' %}", "contents": "{% extends '${1:base.html}' %}$0" },
{ "trigger": "var: {{ ... }}", "contents": "{{ $1 }}$0" },
{ "trigger": "block: {% block ... %}...{% endblock %}", "contents": "{% block $1 %}$0{% endblock %}" },
{ "trigger": "block: {% block ... %}\\n...\\n{% endblock %}", "contents": "{% block $1 %}\n$0\n{% endblock %}" },
{ "trigger": "for: {% for ... in ... %}...{% endfor %}", "contents": "{% for $1 in $2 %}\n\t$0\n{% endfor %}" }
]
}
However, the popup is only automatically showing up when I try to use it in this file:
When in an HTML, txt, or py file, however (at least those are the three I tested so far), although the snippet expands properly when you hit tab (the trigger key), the popup dialog does not display unless and until you hit the tab key.
How do I get the popup to automatically display in these other types of files?
Open your user preferences and add the text scope (e.g. text or text.html) to the auto_complete_selector setting