Taking a form response, making an api call then displaying the api call in Django

Viewed 791

I'm trying to have a Django form capture data from a user's input, take the input to make an API call to Aylien API and display the raw json result on the same page.

I'm able to take the form input and successfully make an API call & get the JSON to print on the console, but am having a hard time displaying the call's result on the page.

I keep getting UnboundLocalError: local variable 'api_response' referenced before assignment error. Code below

models.py

from django.db import models

# Create your models here.
class News(models.Model):
    title = models.TextField(max_length=120)

form.py

from django import forms
from .models import News

class NewsForm(forms.ModelForm):
    class Meta:
        model = News
        fields = [
            'title']

views.py

from django.shortcuts import render
from .models import News
from .form import NewsForm
import requests
import aylien_news_api
from aylien_news_api.rest import ApiException

def news_create_view(request):
    ## link form to model for gathering search term from user
    form = NewsForm(request.POST)

    if form.is_valid():
        # create an instance of the aylien api class
        api_instance = aylien_news_api.DefaultApi()

        ## build opts for api call from the response from the user
        opts = {
            'title': form.cleaned_data['title'],
            'language': ['en'],
            'not_language': ['es', 'it'],
            'published_at_start': 'NOW-7DAYS',
            'published_at_end': 'NOW'
        }
        try: 
            # List the stories
            api_response = api_instance.list_stories(**opts)
        except ApiException as e:
            print("Exception when calling DefaultApi->list_stories: %s\n" % e)

        ## re-instantiate the form and save to admin    
        form.save()
        form = NewsForm()

    else:
        form = NewsForm()

    ## context for models
    context = {
        'form': form,
        'api_response': api_response
    }

    ## render pages in Django dynamically (static HTML is slow to load)
    return render(request, "news/show_result.html", context)

show_result.html

<div class="row">
    <form method="GET"> {% csrf_token %}
        <!-- the 'as_p' method turns the django-rendered form into html for the user -->
        {{ form.as_p }}
        <input type="submit", value="Search" />

    </form>

</div>
<div class="row"> 
    {{ api_response }}
</div>

I'm obviously doing something wrong here, just can't seem to figure out what

1 Answers

You are getting this error because your form is invalidated, and api_response will only be defined if the form is valid.

To fix your problem, Change this:

form = NewsForm(request.POST)

To this:

form = NewsForm(request.POST or None)

If you make a GET to your view, your form will be invalid if you pass an empty request.POST, so you need to pass None instead.

Lastly, I'd recommend adding api_response = None in your else clause. This will prevent api_response from ever being undefined, and your server won't give a 500 error if someone is tampering with the form.

Related