【问题标题】:Call an API on my server from another view从另一个视图调用我服务器上的 API
【发布时间】:2011-09-25 08:47:04
【问题描述】:

所以,这里有点奇怪。我有一个 Django 项目,使用 TastyPie 为其 API 和一些视图/模板提供动力,这些视图/模板将用于为各种站点提供插件。我被要求使用我们的 API 来处理对插件的请求,而不是将这个插件构建为标准的 Django 模板,这意味着我正在从另一个视图调用我的服务器上的一个视图,并且由于某种原因它不起作用与我的任何观点。供参考:

#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)

以及对应的urls.py(在不同的应用中):

#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()

关于如何解决这个问题的任何想法?我找不到任何关于这个主题的著作。

编辑:更具体地说,发生的事情是,当我加载任何这些视图时,它们会挂起试图读取 api 页面。此外,我的服务器没有显示任何正在处理的请求的迹象。 (虽然我可以直接加载api页面。)

【问题讨论】:

  • 除非您使用 AJAX,否则我认为以这种方式构建网站没有任何好处。我认为您的实际问题是与您的老板交谈并告诉他他的计划没有多大意义(当然不是那些确切的话)。
  • 老实说,我也倾向于该解决方案,尽管我觉得无论如何这应该是可能的。
  • 更具体地说,发生的事情是,当我加载任何这些视图时,它们会挂起试图读取 api 页面。此外,我的服务器没有显示任何正在处理的请求的迹象。 (虽然我可以直接加载 api 页面。)

标签: django api view


【解决方案1】:

现在您的评论已经澄清了情况,我可以猜测问题所在。那是您使用的是内置的开发服务器,它是单线程的。因此,当它处理原始请求时,它无法处理对另一个 URL 的内部请求 - 所以它会无限期地挂起。

正如毛指出的那样,解决方案是考虑更好的架构。如果你不能这样做,你可能会幸运地使用gunicorn 之类的东西而不是内置服务器。

【讨论】:

    【解决方案2】:

    特别是 Tastypie,如果需要,您可以在视图中使用资源,直接访问对象并调用 get 方法并构建包。

    您可以找到方法:http://django-tastypie.readthedocs.org/en/latest/cookbook.html

    转到标题为 - 在常规视图中使用您的资源的部分

    【讨论】:

      【解决方案3】:

      同意,您的开发服务器可能只有一个实例。在不同的端口上启动另一个。 IE/ SITE_NAME = "http://localhost:8001/"

      【讨论】:

        【解决方案4】:

        好的,所以我已经说过让视图针对其他视图发出 HTTPRequest 有点愚蠢,但我确实知道您目前的问题是什么。您正在调用json.loads(urllib.urlopen(SITE_NAME + uri)),但urllib.urlopen 返回的是一个类似文件的对象,而不是字符串,所以它实际上应该是json.load(urllib.urlopen(SITE_NAME + uri))

        【讨论】:

        • 显然不是,尽管以后可能会出现问题-我已设法将其隔离为“urllib.urlopen(url)”。另外,我在终端中注意到由于某种原因没有请求到达服务器(其他页面不是这种情况)。
        • 您是否有任何理由在某些地方使用urllib2.build_opener().open(url) 而不仅仅是urllib.urlopen(url)
        【解决方案5】:

        我刚刚遇到了同样的问题,即从托管的同一台服务器调用 API。正如丹尼尔所建议的,我能够通过在 gunicorn 中使用多线程来解决这个问题:

        gunicorn --certfile=crt --keyfile=key --bind 0.0.0.0:8000 app.wsgi  --threads 5
        

        【讨论】:

          猜你喜欢
          • 2022-12-16
          • 2017-07-10
          • 2013-07-17
          • 1970-01-01
          • 2012-06-25
          • 2014-08-03
          • 2017-10-07
          • 1970-01-01
          • 2020-04-27
          相关资源
          最近更新 更多