2016-04-14 9 views
1

Ich mache einen API-Aufruf mit Anfragen in einer Django-Anwendung. Ich bekomme immer einen Schlüsselfehler beim Namen. Die JSON-Antwort ist ziemlich groß, also wähle ich nur bestimmte Felder aus, um sie zu verwenden. Aber der Fehler ist auf dem allerersten Element in der JSON-Liste.Parsen von JSON mit Anfragen in Django

Die ersten paar Zeilen des json wie folgt aussieht,

"cards": [ 
    { 
     "name": "Air Elemental", 
     "manaCost": "{3}{U}{U}", 
     "cmc": 5, 
     "colors": [ 
     "Blue" 
     ], 
     "type": "Creature — Elemental", 
     "types": [ 
     "Creature" 
     ], 
     "subtypes": [ 
     "Elemental" 
     ], 

Und ich meiner Meinung nach die json wie dies am Parsen

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') 

Der Fehler

KeyError at /graphs/graphs/ 
'name' 

Und ich greife aus meiner Sicht auf die Daten wie folgt zu:

{% 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 %} 

Warum erhalte ich den Schlüsselfehler?

+1

Können Sie nicht verwenden [ 'req.json()'] (http : //docs.python-requests.org/en/master/user/quickstart/#json-response-content), um die Antwort direkt auf das JSON-Objekt zu konvertieren. – AKS

Antwort

3

Wenn Sie das tun

json.loads(req.content.decode()) 

Sie erhalten ein Wörterbuch mit einem Schlüssel, cards.

{'cards': [<list of cards>]} 

Es macht keinen Sinn, dass, um jsonList zu anhängen, weil dann Sie haben,

[{'cards': [<list of cards>]} 

und wenn Sie diese Liste durchlaufen, können Sie die einzelnen Wörterbuch erhalten, die Sie mit gestartet. Wie bereits erwähnt, hat dieses Wörterbuch einen einzigen Schlüssel, cards, so dass Sie den Schlüsselfehler erhalten, wenn Sie versuchen, auf den Schlüssel name zuzugreifen, der nicht existiert.

Sie möchten wirklich [<list of cards>] durchlaufen, also setzen Sie stattdessen jsonList auf diese Liste.

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) 

Wie in den Kommentaren und anderen Antworten erwähnt, können Sie die json() Methode Wunsch, Ihren Code zu vereinfachen verwenden:

req = requests.get('https://api.magicthegathering.io/v1/cards') 
    jsonList = req.json()['cards'] 
    for cards in jsonList: 
     ... 
+0

Greife ich immer noch auf die gleiche Weise in der Vorlage? für Schlüsselkarten {{key.name}} Oder wären es cardData anstelle von Karten? Weil ich das neue Diktat durchspiele, das wir erstellt haben? – wuno

+0

In Ihrer 'return render()' Zeile haben Sie eine Liste 'data' an die Vorlage übergeben. Daher können Sie '{% für Karte in Daten%} {{card.name}} ... {% endfor%}'. – Alasdair

+0

Es tut mir leid, ich möchte das wirklich verstehen. Wo kommen Daten ins Spiel? Wir ca ;; ot KartenDaten. aber wenn ich Daten verwende, wird der Vorname gerendert. Sind Daten nur in die Vorlage integriert? – wuno

2

Da der Schlüssel name nicht in der cards dict. Gefunden werden kann.

Um dies zu debuggen, sollten Sie wahrscheinlich einen Ausdruck jedes Kartendiktats machen und sehen, welches Diktat irregulär ist.

Viel Glück!

+0

Aber der Fehler ist auf der Ansicht nicht die Vorlage. – wuno

+0

cardData ['name'] = cards ['name'] – Snuggert

+0

Mache einen Ausdruck von Karten, um zu sehen, ob der Name tatsächlich da drin ist. – Snuggert

2

warten Sie, Ihr json ist

"cards": [ 
    {"name": "Air Elemental",...} 
] 

Sie es dann laden wie diese

jsonList = [] 
jsonList.append(json.loads(req.content.decode())) 

Ist es nicht jsonList

[ 
    {"cards": [{"name": "Air Elemental",...}]} 
] 

machen, wenn Sie über sie iterieren, Sie‘ ll bekommen {"cards": [{"name": "Air Elemental",...}]}, und anscheinend hat es keinen Schlüssel name. Sie müssen über jsonList['cards'] iterieren.

+0

Danke für Ihre Hilfe. Ich habe das in 3 anderen Apps gemacht und es hat perfekt funktioniert. Die Dekodierung ist, weil es ein JSON-Objekt erhalten muss Str, nicht 'Bytes' ohne die Dekodierung. Willst du mir bitte ein Beispiel deines Vorschlags mit Liste zeigen? Ich nehme an, dass ich Probleme habe, weil das Format des JSON nicht wie die anderen 3 Apps ist, in denen ich das gemacht habe. – wuno

+0

Was ich von deinem Beitrag sehe, ist wie @ laike9m. Es geht nicht um die Dekodiermethode, sondern um dein Json-Objekt. Warum nicht das "cards" -Objekt ausdrucken, um zu sehen, was genau es ist? @wuno – zhangyangyu

+0

Wenn ich (req.content) alle JSON-Dumps drucke. Ich bin total verwirrt, nachdem ich all deine Antworten gesehen habe. Wie ich schon sagte, die letzten drei Apps, die ich geschrieben habe, habe ich genauso gemacht. Kannst du bitte genauer angeben, was mit meinem Code falsch aussieht oder mir vielleicht einen besseren Weg zeigen, dies zu tun? Ich würde dich sehr schätzen. – wuno

1

Wenn Sie die Dokumentation für Anfragen here lesen, jsonList = req.json() wird ein Wörterbuch/Liste der dicts zuweisen zu dem JSON entspricht, die Sie von der externen API Ressource empfangen (und ist wahrscheinlich besser lesbar als json.loads(...) aufrufen.

würde ich vermuten, dass die KeyError Sie bei Ihrer Linie geworfen wird cardData['name'] = cards['name'] weil die JSON Dekodierungsprozess funktioniert nicht wie erwartet empfangen.

dass Failing, haben Sie überprüft, dass Sie durch die richtige Template-Variable sind Iterieren (for key in data) seit das scheint das zu sein, was du passierst grob zur Vorlage.