改变商店的URL时ExtJS 5应用程序+ Django休息框架CORS错误

时间:2014-12-17 16:17:53

标签: django extjs cors django-rest-framework django-cors-headers

我正在开发一个使用Django-rest-framework服务的ExtJS应用程序。我正在使用CORS标头来从服务中获取数据(https://github.com/OttoYiu/django-cors-headers)。

在某个时间点,我想要从商店更改网址。当我这样做时,我得到以下错误:

XMLHttpRequest cannot load http://10.98.0.241:8000/reacsearch/as?_dc=1418831884352&page=1&start=0&limit=25. The request was redirected to 'http://10.98.0.241:8000/reacsearch/as/?_dc=1418831884352&page=1&start=0&limit=25', which is disallowed for cross-origin requests that require preflight.

在settings.oy中,我为CORS

定义了以下属性
CORS_ALLOW_METHODS = (
        'GET',
        'OPTIONS'
    )

CORS_ORIGIN_ALLOW_ALL = True

当我使用URL列出数据库中的所有元素时,这可以正常工作,但是当我更改另一个URL的存储时,我得到上面的错误。此链接在浏览器中也可以正常工作。

商店网址更改是这样做的:

var store = Ext.getStore(storeName);
store.getProxy().setUrl(newURL);
store.load();

视图之间的区别在于,应用程序上的两个是视图集,而另一个只是一个通用列表

class Example1viewset(viewsets.ModelViewSet):
    """
    API endpoing that allows metabolites to be viewed.
    """
    queryset = examples1.objects.all()
    serializer_class = Example1Serializer

class Example1SearchList(generics.ListAPIView):
    serializer_class = Example1Serializer

    def get_queryset(self):
        queryset = Example.objects.all()

        if 'attr' in self.kwargs:
            queryset = queryset.filter(Q(attribute1__contains=self.kwargs['attr']) | Q(attribute2__contains=self.kwargs['abbr']))

        return queryset

就像我提到的那样,两个示例在浏览器中都能正常工作(甚至可以通过网络中的其他计算机访问),但是在应用程序中更改商店的URL时,我收到了CORS错误。有谁知道为什么会这样?

谢谢。

修改

只是为了澄清,问题不在于更改商店的网址。当我尝试将这些URL设置为默认值时,但从应用程序访问时它们不起作用。

我的urls.py文件:

router = routers.DefaultRouter()
router.register(r'example', views.Example1ViewSet)

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
    url(r'^', include(router.urls)),
    url(r'^reacsearch/(?P<attr>.+)/$', Example1SearchList.as_view()),
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))

问题是否与我没有将搜索列表添加到路由器这一事实有关?

EDIT2

问题解决了,因为我试图从其他域获取数据。我在Extjs中将商店的类型更改为jsonp,并且我还允许我的休息服务将数据呈现为jsonp。

只是提醒一下,如果有人遇到同样的问题,有必要将?format = jsonp添加到商店网址:

http://my/url/?format=jsonp

1 个答案:

答案 0 :(得分:3)

由于它看起来像是一个替代解决方案,我将解释问题的原因以及该替代方案的工作原理。

  

XMLHttpRequest无法加载first url。请求被重定向到“second url”,对于需要预检的跨源请求,该请求不被允许。

这里的问题是你告诉Django强制执行尾部斜杠,这使得它自动将没有尾部斜杠的URL重定向到带有斜杠的url,假设存在一个斜杠。这就是为什么,如错误中所述,请求被重定向到第二个URL,您可以告诉它有缺少的尾部斜杠。这由the APPEND_SLASH Django setting控制,默认为True

问题在于,当CORS正在执行预检请求时,它允许它确定是否可以进行请求,在请求的URL 处必须有一个有效的响应。由于您正在重定向请求,因此预检请求会失败,并且您会在没有您的信息的情况下陷入困境。

您可以通过在代码中添加尾部斜杠来解决此问题。似乎有一些solutions for doing this with ext,但我个人不能推荐一个具体的information on CORS vs JSONP。您也可以手动设置网址以使用尾部斜杠,这听起来就像您之前所做的那样。

或者你可以使用JSONP ......

您已找到替代解决方案,即使用JSONP发出请求而不是依赖CORS。这可以解决预检问题并适用于所有主流浏览器,但仍有一些缺点需要考虑。您可以通过环顾四周找到更多{{3}}。

如果您想要对API进行任何更改,那么您将需要CORS,因为JSONP仅支持GET个请求。还有其他优点,例如中止请求的能力,也包含CORS。