I have the following output from a ansible os_stack create task:
"outputs": [{"description": "lb", "output_key": "lb_1", "output_value": "10.1.1.11"}, {"description": "lb", "output_key": "lb_2", "output_value": "10.1.1.12"}, {"description": "web", "output_key": "web_1", "output_value": "10.1.1.13"}, {"description": "web", "output_key": "web_3", "output_value": "10.1.1.14"}, {"description": "web", "output_key": "web_2", "output_value": "10.1.1.15"}]
I need to output this data into a file.
I've tried building a jinja2 template with the following code
{%- set ip_specs = {} -%}
{% for group in outputs[0].description -%}
{%- set net_info=[] -%}
{%- set index = [ 1 ] -%}
{% for ip in outputs[0].output_value[group] -%}
{%- do net_info.append({'net_info': {'ip': ip }, 'index': index[0] }) -%}
{%- do index.append(index.pop()+1) -%}
{%- endfor %}
{% if net_info -%}
{%- do ip_specs.update({ group: net_info }) -%}
{% endif -%}
{%- endfor %}
{{ { 'vm_list': ip_specs } | to_yaml }}
I'm expecting the following format:
vm_list:
lb:
- net_info: {ip: 10.1.1.11}
index: 1
- net_info: {ip: 10.1.1.12}
index: 2
web:
- net_info: {ip: 10.1.1.13}
index: 1
- net_info: {ip: 10.1.1.14}
index: 2
- net_info: {ip: 10.1.1.15}
index: 3
but i'm getting the following error from ansible:
AnsibleUndefinedVariable: 'ansible.utils.unsafe_proxy.AnsibleUnsafeText object' has no attribute u'i'
There are a few logic errors in your template. Try this instead:
{%- set host_groups = {} -%}
{%- for output in outputs -%}
{%- if output["description"] not in host_groups -%}
{%- do host_groups.update({output["description"]: []}) -%}
{%- endif -%}
{%- set index = host_groups[output["description"]]|length + 1 -%}
{%- do host_groups[output["description"]].append({"net_info": {"ip": output["output_value"]}, "index": index }) -%}
{%- endfor -%}
{{ { 'vm_list': host_groups } | to_yaml }}
Related
i'm working with ckanext-scheming and trying to add a custom field similar to repeating subfields with few modifications (below are few files that define the field and it's behavior), for the most part it works correct but it doesn't get submitted to the database (although once i intercept the package create action, i can see the field data is there), any ideas are welcomed:
the scheming yaml part:
- field_name: tag_string
label: Tags
form_snippet: custom_tags.html
display_snippet: modified_repeating_subfields.html
help_text: >-
Additional keywords useful for ...
the form snippet:
{% import 'macros/form.html' as form %}
{% asset 'ckanext-dalrrdemcdcpr/facets-active-js' %}
{%
set options=[
{'value': '001', 'text': _('Discipline')}
, {'value': '002', 'text': _('Place')}
, {'value': '003', 'text': _('Stratum')}
, {'value': "004", "text":_("Temporal")}
, {'value': "005", "text":_("Theme")}
]
%}
{%- set extra_html = caller() if caller -%}
{% set classes = (classes|list) %}
{% call form.input_block(field.field_name, field.label, "", classes, extra_html=extra_html, is_required=false) %}
<div class="repeating_custom_tag_row-index-0" id="repeating_custom_tag_row-index-0" data-module="repeating_tags_handler">
<div class="metadata_tags_holder">
<div class="metadata_tags_styler">
<div class="metadata_tags_input">
<label for="custom_delete" class="input-group-text">{{ _('Input tag') }}</label>
<input class="form-control" id="repeating_custom_tag_row-index0-tag-input-index-0" type="text" name="repeating_custom_tag_row-index0-tag-input-index-0" value="" placeholder=""/>
</div>
<div class="metadata_tags_type_select">
<div><label for="tag_select" class="input-group-text">{{_('Input tag type')}}</label></div>
<select id="tag_select" name="repeating_custom_tag_row-index0-select-input-index-0" required>
{% for option in options %}
<option value="{{ option.value }}"{% if option.value == selected %} selected{% endif %}>{{ option.text or option.value }}</option>
{% endfor %}
</select>
</div>
<div class="tags_buttons_wrapper">
<div class="tags_handling_buttons">
<button class="btn btn-success add_metadata_tags_btn">Add</button>
<button class="btn btn-danger remove_metadata_tags_btn"><i class="fa fa-trash"></i>Remove</button>
</div>
</div>
</div>
</div>
</div>
{% endcall %}
the display snippet (don't think it's useful):
{% set fields = data[field.field_name] %}
{% block subfield_display %}
{% for field_data in fields %}
<div class="panel panel-default">
<div class="panel-body">
<dl class="scheming-subfield-list">
{% for subfield in field.repeating_subfields %}
<dt class="dataset-label">
{{ h.scheming_language_text(subfield.label) }}
</dt>
<dd>
{%- snippet 'scheming/snippets/display_field.html',
field=subfield,
data=field_data,
entity_type=entity_type,
object_type=object_type
-%}
</dd>
{% endfor %}
</dl>
</div>
</div>
{% endfor %}
{% endblock %}
this is how the relevant part of the form looks (the tags):
the js module controlling tags fields behavior:
ckan.module("repeating_tags_handler", function ($){
/*
control muliple interaction regarding the tags
section, handles both css and buttons behavior.
*/
return {
initialize: function(){
$.proxyAll(this,/_on/);
// set the styles before copying the section
let add_btns = $(".add_metadata_tags_btn")
add_btns.each((idx,add_btn) => {add_btn.style.marginRight="2px"})
$(document).on('click','.add_metadata_tags_btn',this._on_add_tags)
$(document).on('click','.remove_metadata_tags_btn',this._on_remove_tags)
let repeating_fields_wrapper = $(".repeating_custom_tag_row-index-0")
repeating_fields_wrapper.css({"margin-bottom":"30px"})
let tags_holder = $(".metadata_tags_holder")
tags_holder.css("width:100%")
$(".metadata_tags_styler").css({"width":"100%", "display": 'flex', 'flex-direction': 'row'})
$(".metadata_tags_input").css({"width":"40%"})
$(".metadata_tags_type_select").css({"width":"30%"})//tag_select
$("#tag_select").css({"width":"100%", "height":"34px", "margin-left":"4px"})
$(".tags_buttons_wrapper").css({"margin-left": "4px", "padding-top": "2px"})
$(".tags_handling_buttons").css({"width":"100%","padding-top":"22px", "display": "flex", "flex-direction": "row", "margin-left":"4px"})
this.section_html = tags_holder.html()
const config = { attributes: true, childList: true, subtree: true };
//const added_items_observer = new MutationObserver(this.added_items_mutation_observer);
//added_items_observer.observe(repeating_fields_wrapper.get(0), config)
},
_on_add_tags:function(e){
e.preventDefault()
//let search_parent = e.target.parentElement.parentElement.parentElement.parentElement
let search_parent = e.target.closest(".metadata_tags_styler")
let new_index = Array.from(search_parent.parentNode.children).indexOf(search_parent) +1
let new_index_text = `index-${new_index}`
this.section_html = this.section_html.replace(/index-[0-9]/g, new_index_text)
this.el.append(this.section_html)
},
_on_remove_tags:function(e){
e.preventDefault()
let removed_tag_row = e.target.closest(".metadata_tags_styler")
//let removed_tag_row = e.target.parentElement.parentElement.parentElement.parentElement
removed_tag_row.remove()
},
}
})
and finally this is a Runtime error screenshot i raised for you - dear - to see the tags data is there:
thank you!
I am getting this error
"Structured data with syntax errors detected
Invalid items are not eligible for Google Search's rich results." Unparsable structured data
here is the code structured-data.liquid for How to resolve it and I also want to add FAQs schema to Shopify how to add FAQs schema to Shopify.
{%- if template contains 'index' -%}
<script type="application/ld+json">
{
"#context": "https://schema.org",
"#type": "WebSite",
"name": {{ shop.name | json }},
"url": "https://{{ shop.domain }}",
"potentialAction": {
"#type": "SearchAction",
"target": "https://{{ shop.domain }}{{ routes.search_url }}?q={query}",
"query-input": "required name=query"
}
}</script>
{% endif %}
{%- if template contains 'product' -%}
{%- if product.available == true -%}
{%- if product.selected_or_first_available_variant.inventory_policy == "continue" -%}
{%- assign availability = "PreOrder" -%}
{%- else -%}
{%- assign availability = "InStock" -%}
{%- endif -%}
{%- else -%}
{%- assign availability = "OutOfStock" -%}
{%- endif -%}
<script type="application/ld+json">
{
"#context": "https://schema.org",
"#id": {{ canonical_url | json }},
"#type": "Product",
"brand": {
"#type": "Brand",
"name": {{ product.vendor | json }}
},
"sku": {{ product.selected_or_first_available_variant.sku | json }},
"description": {{ product.description | strip_html | json }},
"url": {{ canonical_url | json }},
"name": {{ product.title | json }},
{%- if product.featured_image -%}
"image": "https:{{ product.featured_image | product_img_url: 'grande' }}",
{%- endif -%}
"offers": {
"#type": "Offer",
"priceCurrency": "{{ shop.currency }}",
"price": "{{ product.selected_or_first_available_variant.price | money_without_currency | remove: "," }}",
"availability": "http://schema.org/{{ availability }}",
"url": {{ canonical_url | json }},
"sku": {{ product.selected_or_first_available_variant.sku | json }},
"seller": {
"#type": "Organization",
"name": {{ shop.name | json }}
}
{%- if product.selected_or_first_available_variant.barcode.size == 12 -%},
,"gtin12": "{{ product.selected_or_first_available_variant.barcode }}"
{% endif %}
{%- if product.selected_or_first_available_variant.barcode.size == 13 -%},
,"gtin13": "{{ product.selected_or_first_available_variant.barcode }}"
{%- endif -%}
{%- if product.selected_or_first_available_variant.barcode.size == 14 -%},
,"gtin14": "{{ product.selected_or_first_available_variant.barcode }}"
{%- endif -%}
}
}</script>
{%- endif -%}
{%- if template contains 'article' -%}
<script type="application/ld+json">
{
"#context": "http://schema.org",
"#type": "Article",
"mainEntityOfPage": {{ canonical_url | json }},
"name": {{ article.title | json }},
"headline": "{{- article.title -}}",
"image": [
"{{ article | img_url: 'master' }}"
],
datePublished: "{{- article.published_at | time_tag -}}",
"dateModified": "{{- article.published_at | time_tag -}}",
"author": {
"#type": "Person",
"name": "{{- article.author -}}"
},
"publisher": {
"#type": "Organization",
"name": "{{- shop.name -}}",
"logo": {
"#type": "ImageObject",
"url": "{{- 'logo.jpg' | file_url: 'master' -}}"
}
},
"description": {{- article.excerpt_or_content | strip_html | json -}},
"articleBody": {{- article.content | strip_html | json -}}
}
</script>
{%- endif -%} }
I have a list of 'products'
they are structured like this:
They have a product that act as a parent: "product 1"
and then they have multiple variations of that parent "product 1-small", "product 1-medium", "product 1-large" etc.
but the number of their variations vary, one product may have 2 variations, the other may have 5.
I want to display them like this:
Product 1
small - large
product 2
small - xlarge
how should I do this in liquid on a jekyll static site?
you can view my website and the page I'm referring here:
https://kostasgogas.com/shop/art/prints/new-media-vector/abstract/
where the problem is apparent on the price, and size of each product.
this is an example of my data.yml:
- id: 'first-art'
type: variable
- id: 'first-art-small'
type: variation
position: 1
price: '10'
parent: 'first-art'
- id: 'first-art-medium'
type: variation
position: 2
price: '20'
parent: 'first-art'
- id: 'first-art-large'
type: variation
position: 3
price: '30'
parent: 'first-art'
- id: 'second-art'
type: variable
- id: 'second-art-small'
type: variation
position: 1
price: '10'
parent: 'second-art'
- id: 'second-art-medium'
type: variation
position: 2
price: '20'
parent: 'second-art'
- id: 'second-art-large'
type: variation
position: 3
price: '30'
parent: 'second-art'
- id: 'second-art-x-large'
type: variation
position: 4
price: '40'
parent: 'second-art'
The liquid is as follows (currently counting up to 3 variations because I don't know how to do it):
{%- assign printartworks = site.data.products-prints -%}
{%- for printart in printartworks -%}
{%- if printart.type == "variable" -%}
<h3>
{{ printart.id }}
</h3>
<div>
{%- for variation in site.data.products-prints -%}
{%- if variation.parent == printart.id -%}
{%- if variation.position == "1" -%}
€{{ variation.price }}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
—
{%- for variation in site.data.products-prints -%}
{%- if variation.parent == printart.id -%}
{%- if variation.position == "3" -%}
€{{ variation.price }}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
</div>
{%- endif -%}
{%- endfor -%}
your problem is the variants and the parent are at the same level, you should fix that setting a variants array inside the parent, after that you can use the filters first and last.
the yaml should looks something like that
products-prints:
- id: 'first-art'
type: variable
name: 'add name and other data of the product'
variants:
- id: 'first-art-small'
name: 'small'
position: 1
price: '10'
- id: 'first-art-medium'
name: 'medium'
position: 2
price: '20'
- id: 'first-art-large'
name: 'large'
position: 3
price: '30'
- id: 'second-art'
type: variable
name: 'add name and other data of the product'
variants:
- id: 'second-art-small'
name: 'small'
position: 1
price: '10'
- id: 'second-art-medium'
name: 'medium'
position: 2
price: '20'
- id: 'second-art-large'
name: 'large'
position: 3
price: '30'
- id: 'second-art-x-large'
name: 'x-large'
position: 4
price: '40'
Now the liquid will be:
{%- assign printartworks = site.data.products-prints -%}
{%- for printart in printartworks -%}
<h3>
{{ printart.id }}
</h3>
<div>
<p>
{{ printart.variants.first.name }} - {{ printart.variants.first.price }}
</p>
<p>
{{ printart.variants.last.name }} - {{ printart.variants.last.price }}
</p>
</div>
{%- endfor -%}
now the code will read the first and the last element on your array, if the yaml is on order that should do the trick, is up to you write the file on order.
To be extra careful, you can sort the variants array before read it.
Disclaimer: THIS IS A BAD IDEA. The best solution is to refactor your data, but if you can't edit the data this will work.
Without refactoring the YAML data, your app should make more processing each time the page is visited.
{%- assign printartworks = site.data.products-prints -%}
{%- for printart in printartworks -%}
{%- if printart.type == "variable" -%}
{% assign variants = '' | split: '' %}
{%- for variation in site.data.products-prints -%}
{%- if variation.parent == printart.id -%}
{% assign variants = variants | concat: variation %}
{%- endif -%}
{%- endfor -%}
{% assign variants = variants | sort: "position" %}
<h3>
{{ printart.id }}
</h3>
<ul>
<li>
€ {{ variants.first.price }}
</li>
<li>
€ {{ variants.last.price }}
</li>
</ul>
{%- endif -%}
{%- endfor -%}
i have array line this
setime = ["00:00", "00:30", "01:00", "01:30", "02:00", "02:30", "03:00", "03:30", "04:00", "04:30", "05:00", "05:30", "06:00", "06:30", "07:00", "07:30", "08:00", "08:30", "09:00", "09:30", "10:00", "10:30", "11:00", "11:30", "12:00", "12:30", "13:00", "13:30", "14:00", "14:30", "15:00", "15:30", "16:00", "16:30", "17:00", "17:30", "18:00", "18:30", "19:00", "19:30", "20:00", "20:30", "21:00", "21:30", "22:00", "22:30", "23:00", "23:30"]
and i want check
in view
myListTime= checkDateTime.objects.all().filter(Teacher_id = 1)
i tried in template
{% for i in setime %}
<ul>
{% for j in myListTime %}
{% if j.cuTime in i %}
<li class="active">{{ i }}</li>
{% else %}
<li>{{ i }}</li>
{% endif %}
{% endfor %}
</ul>
{% endfor %}
i need result like this if data matched, li have active class
enter image description here
in db
Rather than iterating over the list of times, you'd be better to use that list in your database query.
If you've got a list you can do __in to check if a list of values exists in the values for a field.
setime = ["00:00", "00:30", ..., "22:30", "23:00", "23:30"]
myListTime_with_time = checkDateTime.objects.all().filter(Teacher_id=1, cuTime__in=setime)
myListTime_without_time = checkDateTime.objects.all().filter(Teacher_id=1).exclude(cuTime__in=setime)
I have a list in October CMS like this:
<ul>
<li {% if this.page.id=='some-id' %} class = "active" {% endif %}>
Item 1
</li>
<li {% if this.page.id=='some-id' %} class = "active" {% endif %}>
Item 2
</li>
<li {% if this.page.id=='some-id' %} class = "active" {% endif %}>
Item 3
</li>
</ul>
However, as you can see there is a lot of repitition so I decided to create array variables. I can pass on a single array variable but I am not sure how to do it for multiple arrays so my code can look something like this:
==
function onStart(){
$this['pageData']=[
'data' => [
'item' => ['Item 1','Item 2','Item 3'],
'id' => ['pageid1','pageid2','pageid3'],
'link' => ['dir/page1','dir/page2','dir/page3']
]
];
}
==
<ul>
{% for items in pageData %}
<li {% if this.page.id == items.data.id %} class="active" {% endif %}>
{{items.data.item}}
</li>
{% endfor %}
</ul>
I know this code is wrong but this is the idea. I can retrieve one object array if I write:
{% for items in pageData.data.item %}
<li>{{items}}</li>
{% endfor %}
But this of course only gives me a list of items inside the 'item' object. I hope I explained it well. Please let me know if I can provide more information to get this problem solved.
You can write it like this
==
function onStart(){
$this['records'] = [
[
'id' => 'pageid1',
'item' => 'Item 1',
'link' => 'dir/page1'
],
[
'id' => 'pageid2',
'item' => 'Item 2',
'link' => 'dir/page2'
],
[
'id' => 'pageid3',
'item' => 'Item 3',
'link' => 'dir/page3'
],
];
}
====
<ul>
{% for record in records %}
<li {% if this.page.id == record.id %} class="active" {% endif %}>
{{record.item}}
</li>
{% endfor %}
</ul>
this will work
if any doubts please comment.