Why is there no output in jinja2 Loop? - jinja2

i try to loop over a dic in my jinja template. But i always get no output.
dic={"SERVICE1" : "tess","SERVICE2" : "test"}
with open(Path(Path.cwd()/"test.jinja")) as f:
template = Template(f.read()).render(data_nebula_docker)
print(template)
My template looks like this:
{% for item in dic %}
{{item}}
{% endfor %}
Normal Variablse are working fine. Does i have some basic misunderstanding?
Thx for your help!

There are a couple of problems with your code. I'm going to assume the indentation issue in your with statement is just a copy-and-paste error, and that your code actually looks like:
with open(Path(Path.cwd()/"test.jinja")) as f:
template = Template(f.read()).render(data_nebula_docker)
print(template)
In your template you're referencing a variable dic, but you aren't passing this to the render method. You want:
from jinja2 import Template
from pathlib import Path
dic = {"SERVICE1": "tess", "SERVICE2": "test"}
with open(Path(Path.cwd() / "test.jinja")) as f:
template = Template(f.read()).render(dic=dic)
print(template)
Which produces:
SERVICE1
SERVICE2
You'll note that this only prints out the keys in your dictionary. When you iterate over a dictionary (in Jinja or Python), you get a list of keys. If you want (key, value) tuples instead, use the .items() method:
{% for item in dic.items() %}
{{item}}
{% endfor %}
Which produces:
('SERVICE1', 'tess')
('SERVICE2', 'test')
Separately, your use of pathlib.Path is a little convoluted; you can write instead:
with (Path.cwd()/"test.jinja").open() as f:
In the above:
It's not necessary to wrap the result of Path() / "string" in a call to Path() (because it's already a Path)
A Path object has an open method, so we can call .open() on the Path that results from Path.cwd()/"test.jinja".
Although in this case, your pathlib based code isn't much of a win over:
with open("test.jinja") as f:

Related

removing brackets when calling data from a multi-dimensional array using JSON on Liquid

The data on JSON would be a multi-dimensional array, called by a Liquid template as follows:
array-inception: [
prompt1: "string",
variable1: "(int/float)",
evento_prompt_2:"string",
variable2:"(int/float)",
],
I tried to call {{ array[0].array-inception[0] }} and I also tried with {{ array[0].array-inception }} as a whole, but always getting brackets on natural language, such as...
[string] [(int/float)]
[[string], [(int/float)], [string], [(int/float)]]
Using the filter {{| concat:}} still leads to...
[string (int/float)]
Is there anyway that I can solve this without using any function on JS or at Liquid? Any filter that I could apply on the later?

Accessing JSON data in template in Django

I have a view that retrieves a JSON file like this:
json_lang = requests.get('path/to/file.json').json()
return render(request, "chat/chatroom.html", {'jsonLang': json.dumps(json_lang)})
Let's say the json file is structured somewhat like this:
{
"en": {
"action.send": "Send",
"chat.joined": "joined the chatroom",
"chat.left": "left the chatroom",
...
}
If I try to access one of those strings in a template like this {{ jsonLang.en.chat.joined }} I get an empty output.
Other methods, like trying to access it like this jsonLang["en"]["chat.joined"] result in an error:
TemplateSyntaxError at /chat/
Could not parse the remainder: '["en"]["chat.joined"]' from 'json_lang.["en"]["chat.joined"]'
What's the correct method to do this?
Firstly, 'jsonLang': json.dumps(json_lang) means that you pass a string to template. You should use 'jsonLang': json_lang to pass it as a Python dictionary.
Secondly, as dictionary lookup in Django templates are implemented with dot notation, this breaks if the key itself contains a dot.
One solution is adding a quick template filter that allows to access dictionary items by keys with dots - Access a dictionary element in the Django template with a variable

Display Twig variable using JSON.stringify

I have a function in a Silex application that executes a cURL statement and returns JSON string which is assigned to the variable curl_result. This variable is then passed into a Twig template like this:
return $twig->render('http.html.twig', ['curl_result' => $result]);
In the Twig template, I am able to display the JSON string variable by using this:
{% if curl_result is defined %}
<pre>{{ curl_result }}</pre>
{% endif %}
which produces this result:
{"ServiceAccount":[{"Type":"MATTER","ID":[{"body":"1980933400...
Alternatively, when I use JSON_PRETTY_PRINT:
{% if curl_result is defined %}
<pre>{{ curl_result|json_encode(constant('JSON_PRETTY_PRINT')) }}</pre>
{% endif %}
the only effect seems to be that it places the JSON string within double-quotes, and escapes the inside double-quotes:
"{\"ServiceAccount\":[{\"Type\":\"MATTER\",\"ID\":[{\"body\":\"1980933400...
Neither of these displays the JSON in a usable manner. I want the JSON to be displayed in a human readable format and would like to use JSON.stringify for that purpose. I am able to use the following javascript code and JSON.stringify some random text like this:
<script>
var jsonString = '{"some":"json"}';
var jsonPretty = JSON.stringify(JSON.parse(jsonString),null,2);
output(jsonPretty);
</script>
If you're still with me after all that, here's my question: How do I bring the Twig variable curl_result into javascript so that I can JSON.stringify it?
In your controller $result is a string, it contains a JSON string but at this point it is only a string. So when you pass it to json_encode it escapes all double quotes because it wants to encode a simple string.
If you want to use json_encode to pretty print this data, you first need to decode this string (exactly what you did in your alternative solution with JSON.parse), then encode it with pretty print option. So in your controller you should have this change:
return $twig->render('http.html.twig', ['curl_result' => json_decode($result)]);
You can then use json_encode to pretty print the curl_result in your twig file the exact way you tried in your second twig snippet:
{% if curl_result is defined %}
<pre>{{ curl_result|json_encode(constant('JSON_PRETTY_PRINT')) }}</pre>
{% endif %}
Alternatively, you can print $result as a JS variable in your twig template file like this:
<script>
var jsonString = '{{ curl_result | raw }}';
var jsonPretty = JSON.stringify(JSON.parse(jsonString),null,2);
console.log(jsonPretty);
</script>
Please note the use of raw filter when printing the json string.

Django- Json data in template

I am accessing an API and get JSON data. I can see that JSON is generated. However I am not able to show it in template.
Below is the sample Json data.
{
"response_code":1,
"response":{
"a":"01/07/2017",
"b":"12",
"c":"23",
"d":"34",
"e":"45",
"f":"56",
},
"error_code":null,
"error_message":null
}
I passed this data in view to template as dataset.
View as asked in comment.
response = requests.request("GET", url, data=payload, headers=headers, params=querystring)
json_string = json.dumps(response)
return render(request,'searchhome.html',{'dataset':json_string})
What I tried in template.
{% for key, value in dataset.items %}
{{key}}: {{value}}
{% endfor %}
Another try
{% for d in dataset %}
{% for key, value in d.response.items %}
{{key}} {{value}}
{% endfor %}
{% endfor %}
Template is not showing any error or any response. What I am doing wrong here?
To iterate, you need it to be a python dict object and not the JSON string.
You can do it using the json package.
Example:
import json
string_containing_json = ".."
data = json.loads(string_containing_json)
Json is just a string arranged in special format. You need to convert it to python objects before using it.
EDIT: I have no idea why the downvote. Judging from the question, this is definitely the issue here. The OP is not converting the json string into dictionary. You can't iterate over a string, like you do a dictionary.
You should not dump the data back to JSON in the view. Once you've done that, it's now a string, so it doesn't have an items method.
You should pass the result of response.json() directly to the template.
I think, within the view, you need to convert the response like this:
import json
response = requests.request("GET", url, data=payload, headers=headers, params=querystring)
json_string = json.dumps(response)
return render(request,'searchhome.html',{'dataset':json_string})
And then, I think, you can access the data as
{{ dataset.response_code }}
{{ dataset.response.0 }}
etc
Finally I could solve it.
My changed view:
response = requests.request("GET", url, data=payload, headers=headers, params=querystring)
response = json.loads(response.content)
json_string = response["response"]
return render(request,'searchhome.html',{'dataset':json_string})
My Template
{% for k,v in dataset.items %}
<tr>
<td>
{{k}}:{{v}}</td>
<tr>
{% endfor %}
Solution came with trying all answers posted and just adding .content to json.loads(response)

Dotliquid JSON Transformation using JSON.net

Im interested in performing JSON transformations and looked into using dotliquid.
In order to avoid having a POCO for the input JSON just to be able to send it as a variable, I would like to send the deserialised JSON. From my understanding, we can't send dynamic to render method, and JObject or JArray does not work as expected. I Tried deserialising to Dictionary< string, object>, but that could not handle nested JSON structures.
liquid
[
{%- for p in data.names -%}
{
"name" : {{ p.name }}
} {%- unless forloop.Last == true -%},{% endunless %}
{%- endfor -%}
]
C# code
Template template = Template.Parse(File.ReadAllText("Maps/account.liquid"));
var json = JsonConvert.DeserializeObject<Dictionary<string, object>>(
#"{ ""names"":[{""name"": ""John""},{""name"":""Doe""}] }");
var jsonHash = Hash.FromAnonymousObject(new { Data = json});
Output
[
{
"name" :
},
{
"name" :
}
]
I know that Microsoft Logic Apps has implemented a similar feature using dotliquid. https://learn.microsoft.com/en-us/azure/logic-apps/logic-apps-enterprise-integration-liquid-transform
What different ways are there? Do I need to parse the JObject/JArray to a nested Dictionary, or what alternatives are there?
You can get it to work using the DictionaryConverter from Deserialize JSON recursively to IDictionary<string,object> and Hash.FromDictionary
var json = JsonConvert.DeserializeObject<IDictionary<string, object>>(#"{ ""names"":[{""name"": ""John""},{""name"":""Doe""}] }", new DictionaryConverter());
var jsonHash = Hash.FromDictionary(json);
var templatetest = "<h1>{{device}}</h1><h2>{{speed}}</h2>{% for client in names %}<h4>{{client.name}}</h4>{% endfor %}";
var template = Template.Parse(templatetest);
var render = template.Render(jsonHash);