In jinja, can I list all variables passed to the render() function? - jinja2

Is it possible to access, in jinja, all variables passed to the render function as dict, without knowing their names?
from jinja2 import Template
template_vars = {"environment": "dev", "var1": "value1", "var2" : "value2", ... , "var12": "value12", ... , "varN": "valueN"}
api_payload = Template("template.json.j2").render(template_vars)
Goal of the template is to create a json file like. Here is base for jinja2.
{
"env": "{{environment}}",
{% for item in [my list of variables passed] %}
{% if '2 'if item %}
"{{item}}": "{{item}}"
{% endif %}
{% endofr %}
}

You could iterate over dictionary like,
for key, value in d.items():
# do whatever with key and value
Or you could pass the data as a list and iterate over it too.

Related

Passing column divided by value as parameter in macro dbt jinja

I'd like to pass a column divided by a value as a parameter in a jinja macro.
I'm using the macro in a dbt model like this {{ pmt('rate'/1200, 'nper', 'pv', 'fv') }}
However, this gives the error message
"Encountered an error: unsupported operand type(s) for /: 'str' and 'int'"
Most likely you have to treat the whole argument as a string literal (quote the whole thing):
{{ pmt('rate/1200', 'nper', 'pv', 'fv') }}
The reason this works is because it is likely that the macro templates this string into SQL code, e.g.,
{% macro pmt(arg1, arg2, arg3, arg4) %}
...
select {{ arg1 }}
...
{% endmacro %}
In this toy example, {{ arg1 }} will take on the value {{ 'rate/1200' }}, which enters the template (unquoted) as
...
select rate/1200
...
which is valid sql (if you have a field called rate).
It's possible this won't work with all macros, though! In dbt, since the macros are typically templating SQL code, you usually want to pass in arguments that contain field or table references as string literals. However, the argument to the macro could stay inside the jinja context, in which case, you'll need to keep the argument unquoted, or modify a variable before it's passed into the jinja macro. As another toy example:
{% macro print_value(val) %}
{{ log(val, info=True) }}
{% endmacro %}
-- if val is a string literal:
{{ print_value('rate/1200') }}
-- $ rate/1200
-- if val is unquoted:
{% set rate = 2400 %}
{{ print_value(rate/1200) }}
-- $ 2

Jinja2 using numeric expressions in Template Expressions

I need to do something apparently very simple:
typedef enum {
{% for e in mylist %}
{{ e }} = 0x{{ '%04X' % (1 << loop.index0) }},
{%- endfor %}
ALL = 0x0FFF
} Sound_Region_t;
but this bombs with "jinja2.exceptions.TemplateSyntaxError: unexpected '<'"
Intention is to get something like:
typedef enum {
foo = 0x0001,
bar = 0x0002,
fie = 0x0004,
fom = 0x0008,
...,
ALL = 0x0FFF
} Sound_Region_t;
I.e.: value is a "walking bit" so I can "bitwise or" together them.
Same behavior if I try to use other variations including "{% with bit = 1 << loop.index %}" or similar.
What am I missing?
Jinja2 does not allow bitwise operators inside the templates, so we need to create a small global function that executes such operators and returns a number:
def leftshift(amount):
return 1 << amount
# Get or create a Jinja2 environment
from jinja2 import Environment
env = Environment(...)
# Add leftshift function to the global context
env.globals['leftshift'] = leftshift
And in the templates now we can call leftshift function with the loop index:
typedef enum {
{% for e in mylist %}
{{ e }} = 0x{{ '{:04X}'.format(leftshift(loop.index0))}},
{%- endfor %}
ALL = 0x0FFF
} Sound_Region_t;

How to create dynamic json using for loop in scala to pass in Gatling post request

I am new to scala ,Any help would be very much appreciated
I have a scala Map which has around 10 ids and 10 weights
Map(id->id,weight->weight)
For post request in gatling , i would like to pass my request on basis of for loop
Expected json: so for example , if there are 10 key values pair in my map - i would like to add 10 inner array in my final json string and there should be a single request.
myjson=
of[
{
"id":pis
"weight":20.3
}
]
Expected json=
of[
{
"id":pis
"weight":20.3
},
{
"id": 2nd value from for loop
"weight":2nd value from for loop
},
{
"id": 3rd value from for loop
"weight":3rd value from for loop
}
]
Gatling provides Pebble Templates which can define and fill your body structure
There is a example how it works: https://gatling.io/2018/11/gatling-3-pebble-templating/
In your case body will be likes:
.body(PebbleStringBody(
"""{
| "of": [ {% for value in mapValues %}
| {
| "id": "{{value.id}}",
| "weight": "{{value.weight}}
| }{% if loop.last %}{% else %},{% endif %}
| {% endfor %}
| ]
|}
|""".stripMargin))
Feeder:
val mapValuesFeeder = Iterator.continually(Map("mapValues" -> List(
Map("id" -> "1", "weight" -> "10"),
Map("id" -> "2", "weight" -> "20"),
)))

Insert Environment Variable using Jinja in SaltStack

I am trying to read a JSON file inside a folder. using import_json.
Here is my code
{% set instance_id = grains['INSTANCE_ID'] %}
INSTANCE_ID Env Var:
environ.setenv:
- name: INSTANCE_ID
- value: {{ grains['INSTANCE_ID'] }}
- update_minion: True
{% import_json "/tmp/$INSTANCE_ID/conf.json" as config_properties %}
But I am getting this error
Data failed to compile:
Rendering SLS 'base:cloud.steps.conf' failed: Jinja error: /tmp/$INSTANCE_ID/conf.json.
Although when I insert the INSTANCE_ID manually it works as expected.
What I want is to be able to insert either $INSTANCE_ID or directly the grain value {{ grains['INSTANCE_ID'] }}
Can someone please help me with this?
Thanks.
{% import_json "/tmp/$INSTANCE_ID/conf.json" as config_properties %}
I imagine you are trying to evaluate the variable $INSTANCE_ID in the above statement. Jinja template evaluates the variables in expression statements.
In this case, the variable is set in the first line, using set
{% set instance_id = grains['INSTANCE_ID'] %}
So, you can use it in expression along with string appends, like
{% import_json "/tmp/" ~ instance_id ~ "/conf.json" as config_properties %}
The above statement should resolve your error.
Also, I would suggest using a variable to evaluate the value of the string expression above, like
{% set conf_json_path = "/tmp/" ~ instance_id ~ "/conf.json" %}
and use it like this
{% import_json conf_json_path as config_properties %}
Hope this help!
In case, you wish to use grains dictionary directly, you can use the value like so
{% set conf_json_path = "/tmp/" ~ grains['INSTANCE_ID'] ~ "/conf.json" %}

Iterating JSON in a django template

I have a json coming from a view in below format in a variable(AllUsers) :
{
"msg": "data found.",
"user": [
{
"fname": "aaa",
"lname": "aaa",
"add": "add1",
"city": "city1",
},
{
"fname": "aaa2",
"lname": "aaa2",
"add": "add2",
"city": "city2",
}
],
"data_status": "active",
"error": false
}
I need to iterate through this JSON in my template and print in below format.So ideally my loop should run 2 times in this case.
name : aaa
name : aaa2
I tried :
{% for myusers in AllUsers %}
name : {{ user.fname}}
{% end for%}
AND
{%with myusers=AllUsers.user%}
{% for user in myusers %}
name : {{ user.fname}}
{% endfor %}
{% endwith %}
But both of them are not working as loops are not iterating even once.In one of SO threads i read ....You shouldn't "convert it to JSON".... but this is not in my hand...i just get the JSON.
Views looks like this :
def somefucn(request):
data = {
"msg": "data found.",
"AllUsers": AllUser ## This is where the above JSON resides
"data_status": "active",
"error": false
}
return TemplateResponse(request, 'path/to/Template.html', data)
Where am i going wrong in the iteration? Please help..
the solution was much easier than I thought:
Let's say you have some JSON like POST request with schema like:
"success": true,
"users": [
{
"userId": "76735142",
"username": "user11_01",
"email": "test11#test.com",
"isTest": false,
"create_at": "2016-01-29T15:41:16.901Z",
"isBlocked": false
}
(All values in the scheme above were given as example)
And you know that to get this response correctly you need next variables in your post body:
{
"id": "",
"pass_code": "",
"search_for": "",
}
Next you need to send POST request with needed values to the API server:
First you need to install necessary components (from your virtualenv):
pip install requests[security]
[security] flag is needed in order to successful response from HTTPS
VIEWS.PY
import requests
from django.shortcuts import render_to_response
def get_user(request):
args = {}
args.update(csrf(request))
post_data = {'id': '1234', 'pass_code': 'pass', 'search_for': '123456'}
response = requests.post('https://example.com/api/', data=post_data)
args['contents'] = response.json()
return render_to_response('your_templae.html', args)
YOUR_TEMPLATE.HTML
<html>
<head>
<title>testing JSON response</title>
</head>
<body>
<div>
{% for user in contents.users %}
{{ user.userId}}<br>
{{ user.username}}<br>
{% empty %}
Nothing found
{% endfor %}
</div>
</body>
</html>
That's it! Have a nice work!
If you mess around you can event fetch headers of this request ;-)
You can use template filter to load json in the template.
Create a file mytags.py as <your-app>/templatetags/mytags.py
The content of mytags.py as:
import json
from django import template
register = template.Library()
#register.filter
def loadjson(data):
return json.loads(data)
Then in your django .htm/.html template load the tags. eg:
{% load mytags %}
{% for foo in YourJsonData|loadjson %}
{{ foo.something }}
{% endfor %}
Hope this helps.
For more info about advanced templating see: http://www.djangobook.com/en/2.0/chapter09.html#extending-the-template-system