2013-08-25 1 views
0

Я занимаюсь самостоятельно программированием менее чем за месяц. Я пытаюсь создать сайт Django, чтобы помочь процессу. Последние три дня я искал решение этой проблемы безрезультатно.Ошибка при попытке импортировать JSON в базу данных Django - TypeError: строковые индексы должны быть целыми числами

Я украл этот код у кого-то из Github, и он отлично работает при вызове файла URL JSON, для которого он был специально написан. Но я пытался изменить его, чтобы работать с другим файлом URL JSON, и он не работает. Это командный файл, который используется для импорта данных в базу данных. Итак, вот что происходит, когда я запускаю команду:

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

Я извиняюсь, если есть слишком много кода ниже, я действительно не знаю, какие вещи люди уже имплицитно знают. Я пытаюсь импортировать поля из каждого игрового элемента, указанного в этом файле JSON. Я только начинаю с 2 полей, чтобы попытаться заставить это работать.

Вы можете просмотреть файл в формате JSON из приведенного ниже URL, но он отформатирован так:

{ 
"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, 

А вот 4 файлов, связанных с командным файлом update_items.py:

модели. ру - эта модель определяет поля базы данных

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 - это командный файл для импорта данных JSON в базу данных

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 - это веб-апи вызов функции вещь

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' 

Так какие идеи? Большое спасибо ...

+0

Не могли бы вы напечатать значение '' result', прежде чем для пункта в результате ['itemdata'] '? –

+0

Да, он печатает то, что я думаю, это строки в Юникоде, например: {u'itemdata ': {u'demon_edge': {u'mc ': False, u'img': u'demon_edge_lg.png ', ... и т. д. – JohnWLIV

ответ

1

Проблема здесь:

for item in result['itemdata'] 

ItemData является ДИКТ (из dicts). В Python, итерация через dict дает ключи : так что item есть «blink», «blades_of_attack» и т. Д., Следовательно, ошибка.

Вам, кажется, не нужны ключи вообще, поэтому вам нужно перебирать result['itemdata'].values().

(Примечание есть ошибка отступы в update_item:. Линия db_item = Item() должна быть отступом в except, в противном случае новый элемент всегда будет создан)

+0

Ничего себе, спасибо! Так что, если бы я хотел, чтобы клавиши также (blink, blades_of_attack и т. Д.), «Result ['itemdata»]: «уже выполняет итерацию только с помощью клавиш, поэтому я могу назначить эти ключи полю в базе данных с тем, как я не так ли, верно? – JohnWLIV

+0

Если вам просто нужны ключи, да. Если вам нужны оба варианта, вы можете использовать 'items()', который дает кортежи (ключ, значение). –

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

Линия result = SteamWrapper.get_item_list делает result точку при методе SteamWrapper имени get_item_list. Возможно, вы намеревались позвонить, набрав SteamWrapper.get_item_list()?

+0

О да, вы правы. И теперь я получаю эту ошибку: TypeError: строковые индексы должны быть целыми числами! И у меня на самом деле была эта ошибка раньше, которая была исходной ошибкой. Может быть, я должен обновить исходное сообщение, чтобы отразить эту ошибку? Спасибо за помощь! – JohnWLIV

+0

Да, обновите вопрос с помощью полной трассировки. –

Смежные вопросы