How to lookup the current context in Nunjucks? - nunjucks

In Handlebars you can use this to look up the current context.
How do you do the same in Nunjucks?
For example, if you wanted to dump the entire context as a JSON string:
<script>window.__config__ = {{ this | dump | safe }};</script>
(But this doesn't seem to work in Nunjucks.)

If you need context then you can add global function
var env = nunjucks.configure([...
...
env.addGlobal('getContext', function() {
return this.ctx;
})
And dump her result in template
{{ getContext() | dump| safe }}

I don't think you the variable this is available on a nunjucks template, but if it's another you wish to inspect you can use the dump method.
{{ users | dump }}
So that will print the json object, which looks really ugly if you have autoscape on.
{{ users | dump | safe }}
this will work just fine
ALTERNATIVELY:
env.addFilter('pprint', function(str, count) {
return JSON.stringify(str, null, 4);
});
{{ users | pprint | safe }}

Related

How to render a literal 'null' in Jinja2 Template

I'm working on an ansible role that allow users to interact with a REST API. I create json.j2 templates that allow me to build the message payload and eventually submit. One of the fields expects either a string value ("") or null.
{
"value": "{{ example.value | default(null, true) }}"
}
This doesn't work and I get this error:
The task includes an option with an undefined variable. The error was: 'null' is undefined
I need that null value and I need to come in as the default value if no other value is provided.
How do I do this?
As pointed in the comments, null has no meaning in Python, None is the Python representation of what your are looking for.
Now, if you want to convert this to a JSON value, then there is a to_json filter in Ansible, so:
'{ "value": {{ example.value | default(None, true) | to_json }} }'
Would end up as:
{ "value": null }

What value will be return that the "return another Undefined value" said in the Ansible document and when we use filter in Jinja2?

I was reading the ansible document and then it said:
Beginning in version 2.8, attempting to access an attribute of an
Undefined value in Jinja will return another Undefined value, rather
than throwing an error immediately. This means that you can now simply
use a default with a value in a nested data structure (in other words,
{{ foo.bar.baz | default('DEFAULT') }}) when you do not know if the
intermediate values are defined.
I can not understand it well. Is it said the expression "{{ foo.bar.baz | default('DEFAULT') }}" will be 'DEFAULT' when foo.bar.baz is not defined or it is said the expression "{{ foo.bar.baz }}" will be another value(mark it as VALUE) when foo.bar.baz is not defined and we need to defind another optional or seccond value like default('DEFAULT') in order to avoid making the expression return VALUE that we do not what it will be at all?
The url containing the statement is at: https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html#omitting-parameters
I got the quotation by a little mouse wheel rotation.
The important part of the statement is in the "when you do not know if the intermediate values are defined".
Prior to 2.8, if you had:
{{ foo.bar.baz | default('DEFAULT') }}
with foo NOT having bar defined (ie. trying to access the attribute baz of the undefined variable bar), the error would be thrown by Jinja2, before reaching the | default(). With the changes referenced by the statement, trying to access baz when bar is not defined (the intermediate value), will not throw an error, but return another undefined, so that the | default() filter will intercept and be able to return DEFAULT.

How do you retrieve the value of a dynamic key name from the results of a register command in ansible

I am looking to retrieve the value of a key (which will have a different key name each time) from a third-party module output.
A simple replication of what I am trying to achieve is as follows:
I have a variable -
secure_name: "ALIAS_HTTPD_HOSTNAME1'
I then run the task:
- name: retrieve param name
shell:
cmd: "echo {{ secure_name }} | cut -'_' -f2-"
register secure_param_name
I have a third module which takes the above {{ secure_param_name.stdout|upper }} as a parameter to retrieve the name value pair from a third party software for holding secure key pairs.
The output of the third party module is stored in a register var called: secure_results
The output of the third party module call is:
{
"changed": false,
"_ansible_no_log: false,
"HTTPD_HOSTNAME1": "SERVERNAME1"
}
if i issue:
-debug: msg="{{ secure_results.HTTPD_HOSTNAME1 }}"
i get the required output SERVERNAME1
I don't however want to have to hardcode every param I wish to retrieve. I wish to be able to use the value of secure_param_name.stdout to make up the variable_name
I have tried:
-debug: msg="{{'secure_results.'+secure_param_name.stdout }}
but this only returns: secure_results.HTTPD_HOSTNAME1
How do I resolve the above dynamic variable name?
using 2 sets of {{ {{ }} }} doesn't work.
I have also tried:
- debug: msg="{{ vars['secure_results.' ~ secure_param_name.stdout] }}"
this errors with 'dict object' has no attibute u'secure_results.HTTPD_HOSTNAME1'
I am a little confused as to why its not finding the dictionary object 'secure_results.HTTPD_HOSTNAME1' when placing that same string in {{ }} retrieves the value as shown in the first debug above.
Any help much appreciated
I think I have this working now by using the following:
- debug: msg="{{ hostvars[inventory_hostname]['secure_results'][secure_param_name.stdout] }}"
would that be the best way to do this?

Sending parameters in a linked route from datatables in Slim 3

I am using datatables for a table in Slim 3 and am trying to link to another page. I can do a link using path_for and "hard code" the variable I want to send, but don't know how to send a variable from datatables.
This is the old code i was using
return '<a href=edit.php?trnum=' + full.trnum + '>Edit or Review</a>';
And this is the slim code I'm using inside twig
return '<a href={{ path_for('edit', {'trannum' : 123}) }}>Edit or Review</a>';
I need to replace the '123' with full.trnum. Everything I try sends the literal string. How do I escape the {{ }} in order to send this variable?
Thats not that easy and beautiful to archieve, because the {{ }} stuff will get parsed by twig, which is on serverside and the full.trnum is (as far as I see) JavaScript, therefore gets executed on clientside.
You could set a placeholder in the path_for-method and then later replace this with the actual value.
Similar to this:
var urlWithPlaceholder = '{{ path_for('edit', {trannum: '%trannum%'}) }}';
var url = urlWithPlaceholder.replace('%trannum%', full.trnum);
return 'Edit or Review';

Render value to tenths place in nunjucks template?

Using the round() filter I can achieve the correct precision to the tenths place as in
{{ value | round(1) }}
however I still want to display the tenths place if value is zero or a whole integer. (0.0 instead of 0, 3.0 instead of 3)
Is there a different method or other way to render all values to the tenths place?
Add you own filter
var env = nunjucks.configure(...
env.addFilter('round1', function(num) {
if (!isNaN(num))
return '???';
return parseFloat(num).toFixed(1);
});
Usage
{{ value | round1 }}
Here is the logic for the custom filter since the round filter will not maintain a tenths place for zero or whole integers:
nunjucks.configure().addFilter('tenths', function(num) {
return parseFloat(num).toFixed(1);
});
Then usage is the same as any filter:
{{ num | tenths }}

Resources