Megan
Megan

Reputation: 175

Parsing and looping through multi-level JSON data in Django

I have a Django website, and I'm making a call to Etsy's API in order to display products on the website. The data has multiple levels (abbreviated below):

{
    "results":[
        {
            "title":"#020",
            "price":"5.99",
            "Images":[
                {
                    "url_570xN":"www.example.com/image1.jpg"
                }
            ]
        },
        {
            "title":"#051",
            "price":"5.99",
            "Images":[
                {
                    "url_570xN":"www.example.com/image2.jpg"

                }
            ]
        },
    ]
}

I can successfully extract data from the results part (title, price) and display it in the template, but I can't figure out how to do the same thing for the Images part (url_570xN). I've spent a few hours trying to find the proper syntax, but I've been unsuccessful.

My views.py:

# Note: The commented lines are the ones giving me problems.
# Removing them yields no errors and displays the info I want,
# minus the images

def products(request):
    parsed_data = []
    response = requests.get('https://openapi.etsy.com/v2/shops/{SHOP_ID}/listings/active?includes=Images:1:0&api_key={KEY}')
    etsy_data = response.json()
    etsy_results = etsy_data['results']
    # etsy_images = etsy_data['results']['Images']

    for results in etsy_results:
        result_data = {}
        result_data['title'] = results['title']
        result_data['price'] = results['price']
        # for Images in etsy_images:
            # result_data['url_570xN'] = Images['url_570xN']
        parsed_data.append(result_data)

    return render(request, 'blog/products.html', {'data' : parsed_data})

My products.html template:

{% for result in data %}
    <p>Title: {{result.title}}
    Price: {{result.price}}
    <img src={{result.url_570xN}} width="200px"></p>
{% endfor %}

And lastly, the error message I get when uncommenting the lines in my views.py:

TypeError at /products/
list indices must be integers or slices, not str

Any help would be much appreciated. Thanks!

EDIT 1: Here is the complete traceback for what I have above:

Environment:


Request Method: GET
Request URL: http://127.0.0.1:8000/products/

Django Version: 2.2.4
Python Version: 3.7.4
Installed Applications:
['django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'blog.apps.BlogConfig',
 'crispy_forms',
 'django_summernote']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/Users/MeganMcCarty/Documents/coding-projects/djangogirls/myvenv/lib/python3.7/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/Users/MeganMcCarty/Documents/coding-projects/djangogirls/myvenv/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/Users/MeganMcCarty/Documents/coding-projects/djangogirls/myvenv/lib/python3.7/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/MeganMcCarty/Documents/coding-projects/djangogirls/blog/views.py" in products
  21.     etsy_images = etsy_data['results']['Images']

Exception Type: TypeError at /products/
Exception Value: list indices must be integers or slices, not str

EDIT 2: I changed my views.py as follows, based on Tom Carrick's answer. Everything works now, thank you so much!

    parsed_data = []
    response = requests.get('https://openapi.etsy.com/v2/shops/{SHOP_ID}/listings/active?includes=Images:1:0&api_key={KEY}')
    etsy_data = response.json()
    etsy_results = etsy_data['results']

    for results in etsy_results:
        result_data = {}
        result_data['title'] = results['title']
        result_data['price'] = results['price']
        result_data['url_570xN'] = results['Images'][0]['url_570xN']
        parsed_data.append(result_data)

    return render(request, 'blog/products.html', {'data' : parsed_data})

Upvotes: 1

Views: 493

Answers (1)

Tom Carrick
Tom Carrick

Reputation: 6616

The problem is that the images are not directly under results, but they are part of each item, at the same level as title and price. There can also be multiple images so I'm assuming here you just want the first one for each product.

So instead you want something like:

def products(request):
    parsed_data = []
    response = requests.get('https://openapi.etsy.com/v2/shops/{SHOP_ID}/listings/active?includes=Images:1:0&api_key={KEY}')
    etsy_data = response.json()
    etsy_results = etsy_data['results']

    for results in etsy_results:
        result_data = {}
        result_data['title'] = results['title']
        result_data['price'] = results['price']
        result_data['url_570xN'] = results['Images'][0]['url_570xN']
        parsed_data.append(result_data)

    return render(request, 'blog/products.html', {'data' : parsed_data})

Upvotes: 2

Related Questions