Error when importing JSON to database Django - TypeError: string indices must be integers

advertisements

I've been self-teaching myself programming for less than a month. I'm trying to build a Django site to help the process. I've spent the last 3 days searching for a solution to this problem to no avail.

I stole this code from someone on Github, and it works fine when calling the JSON URL file for which it was specifically written. But I've been trying to modify it to work with another JSON URL file and it's not working. It's a command file that is used to import data into the database. So here's what happens when I run the command:

PS C:\django-1.5.1\dota\mysite> python manage.py update_items
Fetching item list..
TypeError: string indices must be integers

I apologize if there is too much code below, I really don't know what kinds of things people would already implicitly know. I'm trying to import the fields from each game item listed in this JSON file. I'm just starting with 2 fields to try to get this working.

You can view the JSON file from the URL below, but it is formatted like this:

{
"itemdata": {
    "blink": {
        "id": 1,
        "img": "blink_lg.png",
        "dname": "Blink Dagger",
        "qual": "component",
        "cost": 2150,
        "desc": "Active: Blink - Teleport to a target point up to 1200 units away.  If damage is taken from an enemy hero, Blink Dagger cannot be used for 3 seconds.",
        "attrib": "",
        "mc": 75,
        "cd": 12,
        "lore": "The fabled dagger used by the fastest assassin ever to walk the lands.",
        "components": null,
        "created": false
    },
    "blades_of_attack": {
        "id": 2,

And here are the 4 files related to the command file update_items.py:

models.py -- this model defines the database fields

from django.db import models

class Item(models.Model):
    unique_id = models.IntegerField(unique=True)
    dname = models.CharField(max_length=255)

    def __unicode__(self):
        return self.dname

update_items.py -- this is the command file to import the json data into the database

from django.core.management.base import BaseCommand, CommandError
from django.core.management.base import NoArgsCommand
from items.utils.api import SteamWrapper
from items.models import Item

class Command(NoArgsCommand):
help = 'Fetches and updates the items'

def update_item(self, item):
    try:
        db_item = Item.objects.get(unique_id=item['id'])
        print 'Updating %s..' % item['dname']
    except Item.DoesNotExist:
        print 'Creating %s..' % item['dname']
    db_item = Item()
    db_item.unique_id = item['id']
    db_item.dname = item['dname']
    db_item.save()
    print 'Done.'

def fetch_items(self, result):
        try:
            for item in result['itemdata']:
            self.update_item(item)
        except KeyError:
            print "Error while contacting steam API. Please retry."

def handle(self, *args, **options):
      self.stdout.write('Fetching item list..')
      result = SteamWrapper.get_item_list()
      self.fetch_items(result)
      self.stdout.write('Finished.')

api.py -- this is the web api call function thing

import requests
from mysite import settings_local

class   SteamWrapper():
    ''' Steam API wrapper '''

API_KEY = settings_local.STEAM_API_KEY

@classmethod
def _item_send_request(cls, endpoint, *args, **kwargs):
    params = {'key': cls.API_KEY}
    params.update(kwargs)
    request = requests.get(endpoint, params=params)
    return request.json()

@classmethod
def get_item_list(cls):
    return cls._item_send_request(settings_local.DOTA2_ITEM_LIST_ENDPOINT)

local-settings.py

DOTA2_ITEM_LIST_ENDPOINT = 'http://www.dota2.com/jsfeed/itemdata'

So any ideas? Thanks so much...


The problem is here:

for item in result['itemdata']

itemdata is a dict (of dicts). In Python, iterating through a dict yields the keys: so item there is "blink", "blades_of_attack", and so on, hence the error.

You don't seem to want the keys at all, so you should iterate through result['itemdata'].values().

(Note there is an indentation error in update_item: the line db_item = Item() should be indented within the except, otherwise a new item will always be created.)