Reputation: 9885
I am making an api call with requests in a django application. I keep getting a key error on name. The json response is pretty large so I am only picking certain fields out to use. But the error is on the very first item in the json list.
The first couple lines of the json looks like this,
"cards": [
{
"name": "Air Elemental",
"manaCost": "{3}{U}{U}",
"cmc": 5,
"colors": [
"Blue"
],
"type": "Creature — Elemental",
"types": [
"Creature"
],
"subtypes": [
"Elemental"
],
And in my view I am parsing the json like this,
def graphs(request):
if request.user.is_authenticated():
parsedData = []
req = requests.get('https://api.magicthegathering.io/v1/cards')
jsonList = []
jsonList.append(json.loads(req.content.decode()))
cardData = {}
for cards in jsonList:
cardData['name'] = cards['name']
cardData['manaCost'] = cards['manaCost']
cardData['colors'] = cards['colors']
cardData['type'] = cards['type']
cardData['rarity'] = cards['rarity']
cardData['set'] = cards['set']
cardData['text'] = cards['text']
cardData['flavor'] = cards['flavor']
cardData['artist'] = cards['artist']
cardData['power'] = cards['power']
cardData['toughness'] = cards['toughness']
cardData['layout'] = cards['layout']
cardData['multiverseid'] = cards['multiverseid']
cardData['id'] = cards['id']
parsedData.append(cardData)
return render(request, 'graphs/graphs.html', {'data': parsedData})
else:
return redirect('index')
The Error
KeyError at /graphs/graphs/
'name'
And in my view I am accessing the data like this,
{% for key in cards %}
<tr>
<td>{{ key.name }}</td>
<td>{{ key.manaCost }}</td>
<td>{{ key.colors }}</td>
<td>{{ key.type }}</td>
<td>{{ key.rarity }}</td>
<td>{{ key.set }}</td>
<td>{{ key.text }}</td>
<td>{{ key.flavor }}</td>
<td>{{ key.artist }}</td>
<td>{{ key.power }}</td>
<td>{{ key.toughness }}</td>
<td>{{ key.layout }}</td>
<td>{{ key.multiverseid }}</td>
<td>{{ key.id }}</td>
</tr>
{% endfor %}
Why am I receiving the key error?
Upvotes: 1
Views: 1545
Reputation: 309089
When you do
json.loads(req.content.decode())
You get a dictionary with one key, cards
.
{'cards': [<list of cards>]}
It doesn't make sense to append that to jsonList
, because then you have,
[{'cards': [<list of cards>]}
and when you loop through that list, you get the single dictionary that you started with. As we said before, that dictionary has a single key, cards
, so you get the key error when you try to access the name
key that doesn't exist.
You really want to loop through [<list of cards>]
, so set jsonList
to that list instead.
req = requests.get('https://api.magicthegathering.io/v1/cards')
jsonData = json.loads(req.content.decode())
jsonList = jsonData['cards']
for cards in jsonList:
cardData = {} # move this line inside the loop
cardData['name'] = cards['name']
...
# make sure this line is inside the loop so that you append
# every card to parsedData
parsedData.append(cardData)
As mentioned in the comments and other answers, you could use the request's json()
method to simplify your code:
req = requests.get('https://api.magicthegathering.io/v1/cards')
jsonList = req.json()['cards']
for cards in jsonList:
...
Upvotes: 3
Reputation: 407
If you read the documentation for requests here, jsonList = req.json()
will assign a dictionary / list of dicts corresponding to the JSON you receive from the external API resource (and is probably more readable than calling json.loads(...)
.
I would suspect that the KeyError you are receiving is being thrown at your line cardData['name'] = cards['name']
because the JSON decoding process isn't working as you expect.
Failing that, have you checked that you're iterating through the correct template variable (for key in data
) since that seems to be what you're passing through to the template.
Upvotes: 1
Reputation: 19388
Wait, your json is
"cards": [
{"name": "Air Elemental",...}
]
Then you load it like this
jsonList = []
jsonList.append(json.loads(req.content.decode()))
Doesn't it make jsonList
[
{"cards": [{"name": "Air Elemental",...}]}
]
When you iterate over it, you'll get {"cards": [{"name": "Air Elemental",...}]}
, and apparently it doesn't have key name
. You need to iterate over jsonList['cards']
.
Upvotes: 2
Reputation: 175
Because the key name
cannot be found in the cards
dict.
To debug this, you should probably do a print of each cards dict and see what dict is irregular.
Good luck!
Upvotes: 2