Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call an API on my server from another view

Tags:

django

view

api

So, kind of a in a weird situation here. I've got a Django project using TastyPie to power its API and some views/templates that will be used to power plugins for various sites. Rather than building this plugins as standard Django templates, I've been asked to use our API to process requests to the plugins, which means I'm calling a view on my server from another view, and for some reason that isn't working with any of my views. For reference:

#views.py
from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.template.context import Context, RequestContext
import json, urllib, urllib2

SITE_NAME = "http://localhost:8000/"
API_PATH = "api/v1/"

def aggregate(request):
    template = 'lemonwise/plugins/aggregate.html'
    sku = request.GET.get('sku')
    url = ''.join([SITE_NAME, API_PATH, 'product/?sku=', sku])
    product = json.loads(urllib.urlopen(url).read())['objects'][0]
    return render_to_response(template, product)

def reviews(request):
    template = 'lemonwise/plugins/reviews.html'
    sku = request.GET.get('sku')
    url = ''.join([SITE_NAME, API_PATH, 'product/?format=json&sku=', sku])
    #Comment the next line out and the url is passed correctly
    response = urllib2.build_opener().open(url).read()
    return HttpResponse(url)
    #page = opener.open(url).read()
    #return HttpResponse(url)
    #product = json.loads(urllib2.build_opener().open(url).read())['objects'][0]
    #return HttpResponse(url)
    #reviews = [json.loads(urllib.urlopen(SITE_NAME + uri)) for uri in product['reviews']]
    #return render_to_response(template, {'reviews': reviews})

def survey(request):
    template = 'lemonwise/plugins/survey.html'
    sku = request.GET.get('sku')
    url = ''.join([SITE_NAME, API_PATH, 'product/?sku=', sku])
    product = json.loads(urllib2.build_opener().open(url).read())['objects'][0]
    return render_to_response(template, product)

def mosthelpfulpositive(request):
    template = 'lemonwise/plugins/mosthelpfulpositive.html'
    sku = request.GET.get('sku')
    url = ''.join([SITE_NAME, API_PATH, 'product/?sku=', sku])
    product = json.loads(urllib2.build_opener().open(url).read())['objects'][0]
    uri = product['most_helpful_positive']
    most_helpful_positive = json.loads(urllib.urlopen(SITE_NAME + uri))
    return render_to_response(template, most_helpful_positive)

def mosthelpfulnegative(request):
    template = 'lemonwise/plugins/mosthelpfulnegative.html'
    sku = request.GET.get('sku')
    url = ''.join([SITE_NAME, API_PATH, 'product/?sku=', sku])
    product = json.loads(urllib2.build_opener().open(url).read())['objects'][0]
    uri = product['most_helpful_negative']
    most_helpful_negative = json.loads(urllib.urlopen(SITE_NAME + uri))
    return render_to_response(template, most_helpful_negative)

And the corresponding urls.py (in a different app):

#urls.py    
from django.conf import settings
from django.conf.urls.defaults import patterns, include, url
from django.contrib import admin
from django.contrib.staticfiles.urls import staticfiles_urlpatterns

from tastypie.api import Api
from lemonwise.reviews.api import *

admin.autodiscover()

v1_api = Api(api_name='v1')
v1_api.register(UserResource())
v1_api.register(MerchantResource())
v1_api.register(ProductFamilyResource())
v1_api.register(ProductResource())
v1_api.register(BooleanAttributeResource())
v1_api.register(SlideAttributeResource())
v1_api.register(ProductAttributeResource())
v1_api.register(SubmissionResource())
v1_api.register(ReviewResource())
v1_api.register(ReviewProductAttributeResource())
v1_api.register(CommentResource())
v1_api.register(BestUseResource())
v1_api.register(HelpfulVoteResource())

#Acess the api via http://127.0.0.1:8000/api/v1/user/?format=json

urlpatterns = patterns('',
    url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
    url(r'^admin/', include(admin.site.urls)),

    # Lemonwise apps
    url(r'^reviews/', include('lemonwise.reviews.urls')),

        #API
        url(r'^api/', include(v1_api.urls)),
)

if settings.DEBUG:
    urlpatterns += staticfiles_urlpatterns()

Any idea on how to fix this? I can't find any writings on the subject.

EDIT: More specifically, what's happening is that when I load any of these views they hang trying to read the api page. ALso, my server shows no indications of any requests being processed. (Though I can load the api pages directly.)

like image 365
Ceasar Bautista Avatar asked Jun 29 '11 17:06

Ceasar Bautista


People also ask

Can a server call an API?

Application programming interfaces (APIs) are a way for one program to interact with another. API calls are the medium by which they interact. An API call, or API request, is a message sent to a server asking an API to provide a service or information.

How do I call REST API from another REST API?

Spring boot supports calling one rest service to another rest service using the RestTemplate class. RestTemplate is a synchronised client side class that is responsible for calling another rest service. RestTemplate supports all HTTP methods such as GET, POST, DELET, PUT, HEAD, etc.


2 Answers

Now your comment has clarified the situation, I can take a guess at what the problem is. It is that you are using the built-in development server, which is single-threaded. So while it's processing the original request, it's not able to process the internal request for another URL - so it hangs indefinitely.

The solution, as Mao points out, is to think of a better architecture. If you can't do that, you may have some luck with using something like gunicorn instead of the built-in server.

like image 120
Daniel Roseman Avatar answered Nov 14 '22 03:11

Daniel Roseman


Particular to Tastypie you can use your Resources in views, if you need to, accessing the objects directly and calling the get methods and building the bundle.

You can find out how: http://django-tastypie.readthedocs.org/en/latest/cookbook.html

Go to the section titled - Using Your Resource In Regular Views

like image 45
Travis Chase Avatar answered Nov 14 '22 02:11

Travis Chase