Django template cannot access JSON Key in duplicate quotations: {" 'Key' ": " Value "} - python

My Django app is interacting with an API and displaying results in the templates.
The API result has some normal Key Value pairs and some custom fields which have a Key in double and single quotations.
The key is formatted as " 'custom_field_123' " in the result JSON:
{'cost_price': '0.00', "'asset_field_1234'": None, "'asset_field_5768'": None}
I know this isn't correct JSON format but it's what I have to deal with.
In the Django templates I can use:
<p>{{tower.name}}</p>
for regular format keys.
But the template language will not recognize:
<p>{{tower.'custom_field_123'}}</p>
Or
<p>{{tower.('custom_field_123')}}</p>
Is there a way to access these values or will I have to rename the keys in quotations to access them in the template.

From the template reference docs:
Variable names must consist of any letter (A-Z), any digit (0-9), an underscore (but they must not start with an underscore) or a dot.
So quotes aren't allowed, and the template language has no way to directly access those properties.
You could write your own template tag to look up dictionary items by a variable key (as in this question) but I would suggest fixing your data.

Related

How do I populate a list field variable in Ansible (jinja2, yaml) without inserting the unicode 'u' prefix?

For my python application, I am trying to create and populate a list field in a config file created and deployed by Ansible. Right now it just has one list element (phone_number_), in the future it could have more, hence being a list.
In my jinja2 yaml template I have:
FIELD_NAMES: {{field_names}}
And in my variable var yaml file I have:
field_names: ['phone_number_']
The resulting config file deployed to be server has this line produced:
FIELD_NAMES: [u'phone_number_']
I don't want that unicode "u" in there. How can I get rid of it?
There are to_json and to_yaml filters, that may be helpful.
FIELD_NAMES: {{ field_names | to_json }}
Will give you clean JSON list without unicode markers:
FIELD_NAMES: ["phone_number_"]
You have defined a list with one element:
field_names: ['phone_number_']
I see two options:
1) Reference the variable in your jinja2 template as:
FIELD_NAMES: {{field_names[0]}}
2) Define the variable as a string:
field_names: 'phone_number_'

Flask and jsonify: Escaping characters

I have a flask view which returns some JSON formatted data:
def myview():
entities = get_my_entities()
return jsonify({'entities': entities})
entities if a list of dictionaries; in each dictionary there is a value like http://example.com/get/<user_id>/12345678 where <user_id> is a placeholder where the user should insert an indentifier that that have been given (and which should not appear in the JSON result).
The problem is, the <user_id> gets escaped and appears as %3Cuser_id%3E. Is there a way to stop the characters getting escaped?
Thanks to Martijn. I'm using url_for to build the URLs, and its doing the escaping.

Accessing dict elements with leading underscores in Django Templates

I am trying to access elements of a dict with keys that start with the underscore character. For example:
my_dict = {"_source": 'xyz'}
I'm trying to access them in a Django template. Obviously I realise that you can't access underscored python variables from a Django template (because they are considered private in Python) but this is a dict object where any immutable object is a valid key.
I can't access the above dict in a Django template using {{ my_dict._source }} so I assume Django is preventing it. Is that accurate?
I am kind of hoping Django does something sane with variables that start with underscore like still doing dict lookups (the first thing is supposedly tries) but refuses to do attribute lookups, method calls and list index lookups since an underscored prefixed variable would be invalid. I am quickly loosing hope though.
For the record, I know someone will suggest to just change the dict but this is actually a multi-levelled dictionary returned by the rawes library when executing REST API request on a ElasticSearch instance.
The docs mention that you can't have a variable start with an underscore:
Variable names must consist of any letter (A-Z), any digit (0-9), an underscore (but they must not start with an underscore) or a dot.
but you can easily write a custom template filter to mimic the dictionary's get method:
#register.filter(name='get')
def get(d, k):
return d.get(k, None)
and
{{ my_dict|get:"_my_key" }}
In my case, if I know the dict elements, and it's only one, I prefer to rename the dict key using pop:
my_dict['new_key'] = my_dict.pop('_old_key')
That way I get a new name on the dict, and I can access in the template without problems.

pass list of JSON blobs to django template

How do I pass a python list of JSON blobs to a django template so i can parse it from JSON into a javascript object?
With jquery I have tried the likes of $.parseJSON('{{list_of_JSON_blobs|escapejs}}') in the template, but the "string representation" of a python list is causing syntax errors.
Doing json.dumps(list_of_JSON_blobs) doesn't work either as it stringfys the already serialised JSON blobs.
Currently I am doing dumps( [loads(blob) for blob in list_of_JSON_blobs]) but this is obviously not the optimal method!
worked it out:
use join, and encapsulate the resulting string in paren
'[' + ','.join(list_of_JSON_blobs) + ']'

How do I access dictionary keys that contain hyphens from within a Django template?

We have a system built on a custom database, where many of the attributes are named containing hyphens, ie:
user-name
phone-number
These properties cannot be accessed in templates as follows:
{{ user-name }}
Django throws an exception for this. I'd like to avoid having to convert all of the keys (and sub-table keys) to use underscores just to work around this. Is there an easier way?
A custom template tag is probably the only way to go here if you don't want to restructure your objects. For accessing dictionaries with an arbitrary string key, the answer to this question provides a good example.
For the lazy:
from django import template
register = template.Library()
#register.simple_tag
def dictKeyLookup(the_dict, key):
# Try to fetch from the dict, and if it's not found return an empty string.
return the_dict.get(key, '')
Which you use like so:
{% dictKeyLookup your_dict_passed_into_context "phone-number" %}
If you want to access an object's attribute with an arbitrary string name, you could use the following:
from django import template
register = template.Library()
#register.simple_tag
def attributeLookup(the_object, attribute_name):
# Try to fetch from the object, and if it's not found return None.
return getattr(the_object, attribute_name, None)
Which you would use like:
{% attributeLookup your_object_passed_into_context "phone-number" %}
You could even come up with some sort of string seperator (like '__') for subattributes, but I'll leave that for homework :-)
Unfortunately, I think you may be out of luck. From the docs:
Variable names must consist of any letter (A-Z), any digit (0-9), an
underscore or a dot.
OrderedDict dictionary types support dashes:
https://docs.python.org/2/library/collections.html#ordereddict-objects
This seems to be a side effect of the implementation of OrderedDict. Notice below that the key value pairs are actually passed in as sets. I would bet that the implementation of OrderedDict doesn't use the "key" passed in the set as a true dict key thus getting around this issue.
Since this is a side-effect of the implementation of OrderedDict, it may not be something you want to rely on. But it works.
from collections import OrderedDict
my_dict = OrderedDict([
('has-dash', 'has dash value'),
('no dash', 'no dash value')
])
print( 'has-dash: ' + my_dict['has-dash'] )
print( 'no dash: ' + my_dict['no dash'] )
Result:
has-dash: has dash value
no dash: no dash value

Categories

Resources