更改商店的 URL 时 ExtJS 5 应用程序 + Django 休息框架 CORS 错误 [英] ExtJS 5 application + Django rest framework CORS error when changing URL of store

查看:43
本文介绍了更改商店的 URL 时 ExtJS 5 应用程序 + Django 休息框架 CORS 错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am developing a ExtJS application that uses a Django-rest-framework service. I am using CORS headers to allow fetching the data from the service (https://github.com/OttoYiu/django-cors-headers).

发生的情况是,我想在某个时间点更改商店中的 URL.当我这样做时,我收到以下错误:

What happens is that at a point in time I want to change the URL from the store. And when I do that I get the following error:

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 定义了以下属性

In the settings.oy I define the following properties for the CORS

CORS_ALLOW_METHODS = (
        'GET',
        'OPTIONS'
    )

CORS_ORIGIN_ALLOW_ALL = True

当我使用 URL 列出数据库中的所有元素时,这工作正常,但是当我将商店更改为另一个 URL 时,我收到上述错误.该链接在浏览器中也能正常工作.

This works fine when I use URLs to list all the elements in my database, however when I change the store for another URL I get the error above. Also the link works fine in the browser.

商店网址更改是这样进行的:

The store url change is made this way:

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

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

The difference between the views, is that the two that work on the application are viewsets, while the other is just a generic list

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 错误.有没有人知道为什么会这样?

Like I mentioned both examples work fine in the browser (even accessing through other computers in the network), however in the application when changing the URL of the store I get the CORS error. Does anyone has any idea why this is happening?

谢谢.

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

Just for clarification, the problem is not in changing the url of the store. As I tried to set those urls as defaults, but they are not working when accessing from the application.

我的 urls.py 文件:

My urls.py file:

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

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

Can it be that the problem is related with the fact that I am not adding the search list to the router?

Edit2

问题已解决,因为我试图从不同的域中获取数据.我在 Extjs 中将 store 的类型更改为 jsonp,并且我还允许我的 rest 服务将数据呈现为 jsonp.

Problem solved since I was trying to fetch data from a different domain. I changed the type of store to jsonp in Extjs, and I also allowed my rest service to render data as jsonp.

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

Just a reminder if anyone comes accross this same problem, it is necessary to add ?format=jsonp to the store url:

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

推荐答案

由于看起来像是找到了替代解决方案,我将解释似乎是什么问题以及替代方案为何有效.

Since it looks like an alternate solution was found, I'll explain what the issue appeared to be as well as why the alternative works.

XMLHttpRequest 无法加载first url.请求被重定向到second url",这对于需要预检的跨域请求是不允许的.

XMLHttpRequest cannot load first url. The request was redirected to 'second url', which is disallowed for cross-origin requests that require preflight.

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

The issue here is that you are telling Django to enforce the trailing slash, which makes it automatically redirect urls without a trailing slash to urls with a trailing slash, assuming that one exists. This is why, as stated in the error, the request was redirected to the second url, which you can tell has the missing trailing slash. This is controlled by the APPEND_SLASH Django setting which is True by default.

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

The problem is that when CORS is doing a preflight request, which is what allows it to determine if the request can be made, there must be a valid response at the requested URL. Because you are redirecting the request, the preflight request fails and you're stuck without your information.

您可以通过在代码中添加尾部斜杠来解决此问题.似乎有一些 使用 ext 执行此操作的解决方案,但我个人无法推荐特定的解决方案.您还可以手动设置 url 以使用尾部斜杠,这听起来就像您之前所做的一样.

You can fix this by adding the trailing slash in your code. There appear to be a few solutions for doing this with ext, but I personally can't recommend a specific one. You can also manually set the url to use the trailing slash, which sounds like what you were doing previously.

或者你可以使用 JSONP...

您已经找到了替代解决方案,即使用 JSONP 来发出请求,而不是依赖 CORS.这解决了预检问题并适用于所有主要浏览器,但有一些缺点需要考虑.环顾四周,您可以找到更多有关 CORS 与 JSONP 的信息.

You've found the alternative solution, which is to use JSONP to make the request instead of relying on CORS. This gets around the preflight issue and works in all major browsers, but there are some drawbacks to consider. You can find more information on CORS vs JSONP by looking around.

如果您想将任何更改推送到您的 API,您将需要 CORS,因为 JSONP 仅支持 GET 请求.CORS 还具有其他优势,例如中止请求的能力.

You're going to need CORS if you want to push any changes to your API, as JSONP only supports GET requests. There are other advantages, such as the ability to abort requests, that also comes with CORS.

这篇关于更改商店的 URL 时 ExtJS 5 应用程序 + Django 休息框架 CORS 错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆