jinja: access nested dict without key errors - python

I have a nested dict from a json api call and want to display values from deep within the dict
{{ context.city.houston.street }}
It could be that this value is not present in the dict. How can I avoid key errors in a deeply nested dict in Jinja?

Related

How to Identify an dictionary inside an dictionary

I have a dictionary like this:
test = {'user_id':125, 'company':'XXXX', 'payload': {"tranx": "456b62448367","payload": {"snr": "25%","Soil": 45,"humidity": 85}}}
The requirement is :
the payload inside a dictionary(test), is dynamic sometimes the payload will come and sometimes it won't, and the payload name is temporary, may after some time it will become "abc" or anything.
In this case,
I want to Identify the "test" is a nested dict or not.
If it is nested dict I want to know the "key" of the nested dictionary, How can I solve this.
iterate and check
for key, value in outer_dict.items():
if isinstance(value, dict):
print(key)

Use Variables for key in Jinja Render method

I am trying to iterate over a dictionary and then use the dictionary items to render the template using Jinja.
for key,value in dict.values()
out = template.render(key=value)
I am using undefined=DebugUndefined so that i can use multiple template renders without overwriting the placeholders.
The issue i am facing is that Jinja expects the exact string being passed to the render and i am not able to use the dictionary key. Jinja is trying to find the text {{ key }} for replacement.
Is there a a way I can pass in a variable as the key?
You have to build the dictionary and pass it as a kwargs:
out = template.render(**{key: value})

Having trouble parsing some JSON in python

I'm trying to parse some JSON data from https://mtgjson.com/json/AllCards.json but I'm not sure how to deal with the way its structured. Here's a snippet of my code:
cards = json.loads(open("AllCards.json", encoding="utf8").read())
for card in cards:
print(card)
I was expecting "card" to be a dictionary that I could then use to access attributes, for example "card['name']". However all "card" is in this case is a string containing the the key value so I cant use it to access any of the nested attributes. If I print "cards" though, it outputs the entire JSON document including all of the nested attributes.
I also tried accessing them using cards[0] but this gave me a key error.
I'm obviously missing something here but I cant figure out what.
Iterating a dictionary will by default iterate its keys.
If you walso want the values, you should iterate dict.items() instead:
import json
cards = json.loads(open("AllCards.json", encoding="utf8").read())
for key, value in cards.items():
print(key, value)
value will contain the sub-dict.
It's the same as
import json
cards = json.loads(open("AllCards.json", encoding="utf8").read())
for key in cards:
print(key, cards[key])
If you don't care about the key, you can iterate the values directly:
import json
cards = json.loads(open("AllCards.json", encoding="utf8").read())
for card in cards.values():
print(card)

Unable to store non-characters text in a dictionary in python

I am trying sentiment analysis where I have data like
source_text-> #LiesbethHBC I have a good feeling actually 🙈 its not that long, it's pretty soon!\nAw you deserve these tickets
then! 💖
result_value-> Sentiment(polarity=0.0, subjectivity=0.0)
I want to store this key value pair in a python dictionary.
I tried creating one as:
dict={}
dict[source_text].append(result_value)
but I get KeyError
Is there a way to store such text(just not characters) in a dictionary?
Your problem has nothing to do with "non-character text" (which doesn't mean anything actually), the only requirement for an object to be usable as a dict key is that it's hashable, and there's absolutely no restriction on what you can use as value.
Your problem quite simply comes from the fact that you're trying to get the value for an inexistant key (that's what KeyError means : the key you ask for does not exist in the dict).
Here :
mydict = {}
at this point, mydict is empty so just any item access will raise a KeyError
then you're doing this:
dict[source_text].append(result_value)
which is basically:
something = mydict[source_text] # get value for key `source_text`
something.append(result_value)
Since your dict is empty, the first line WILL obviously raise a KeyError.
If you want to store one unique result_value for each source_text value then the proper syntax is:
mydict[source_text] = result_value
If you want to store a list of result_value for each source_text value then you have to either explicitely test if the key is set, if not set it with an empty list, then append to this list:
if source_text not in mydict:
mydict[source_text] = []
mydict[source_text].append(result_value)
or just use a DefaultDict instead:
from collections import DefaultDict
mydict = DefaultDict(list)
# DefaultDict will automagically create the key with an empty list
# as value if the key is missing
mydict[source_text].append(result_value)
Now I strongly suggest that you invest some time in properly learning Python (hint: there's a quite decent tutorial in the official documentation) if you have to use it, this will save on everyone's time.
The problem is that when you tried to pull out the key #LiesbethHBC I have a good feeling actually 🙈 its not that long, it's pretty soon!\nAw you deserve these tickets then! 💖 in the dictionary which in this case is non-existent, Python gave you a KeyError meaning that the key didn't exist in the dictionary. A simple way to solve this is by initially checking whether you have that particular key in the dictionary, if yes, do whatever you wanna do with it, else create that key first.
By the way, avoid using dict (dictionary datatype) or any other datatypes as a variable name.
This is what you should actually do:
dictionary = {} # Since, 'dict' is the dictionary data-type in Python
if (source_text in dictionary):
# If the key exists...
dictionary[source_text].append(result_value)
else:
# If the key does not exist...
dictionary[source_text] = []
This should help...
Have you tried using '.update' method?
dict = {}
dict.update({'First':'Test'})
dict.update({'Lets Get':'Real'})
print (dict)
Output:
{'Testing': 'Dictionaries', 'Lets Get': 'Real'}
EDIT:
Or even:
dict = {}
dict.update({'Polarity':0.91})
dict.update({'Subjectivity':0.73})
print (dict)
Output:
{'Polarity': 0.8, 'Subjectivity': 0.73}

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.

Categories

Resources