更改商店的 URL 时,ExtJS 5 应用程序 + Django 休息框架 CORS 错误
Posted
技术标签:
【中文标题】更改商店的 URL 时,ExtJS 5 应用程序 + Django 休息框架 CORS 错误【英文标题】:ExtJS 5 application + Django rest framework CORS error when changing URL of store 【发布时间】:2015-02-16 06:19:06 【问题描述】:我正在开发一个使用 Django-rest-framework 服务的 ExtJS 应用程序。我正在使用 CORS 标头来允许从服务 (https://github.com/OttoYiu/django-cors-headers) 中获取数据。
发生的情况是,我想在某个时间点更改商店的 URL。当我这样做时,我收到以下错误:
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'))
可能是问题与我没有将搜索列表添加到路由器这一事实有关吗?
编辑2
问题解决了,因为我试图从不同的域中获取数据。我在 Extjs 中将 store 的类型改为 jsonp,并且我还允许我的 rest 服务将数据呈现为 jsonp。
如果有人遇到同样的问题,请提醒一下,有必要将 ?format=jsonp 添加到商店 url:
http://my/url/?format=jsonp
【问题讨论】:
您确定您的 CORS 标头包含在响应中吗?我会检查你的开发者工具以确保。 我认为问题出在 ExtJS 现在的存储负载上。我正在尝试找出一种使用 JSONP 存储的方法,因为我想从我的应用程序所在的不同域加载数据。仍然有一些空商店,但如果我设法做到这一点,我会更新。感谢您的帮助:) 【参考方案1】:由于似乎找到了替代解决方案,我将解释问题出现的原因以及替代解决方案的工作原理。
XMLHttpRequest 无法加载
first url
。该请求被重定向到“second url
”,这对于需要预检的跨域请求是不允许的。
这里的问题是你告诉 Django 强制使用尾部斜杠,这使得它会自动将没有尾部斜杠的 url 重定向到带有尾部斜杠的 url,假设存在一个斜杠。这就是为什么,如错误中所述,请求被重定向到第二个 url,您可以看出它缺少尾部斜杠。这由the APPEND_SLASH
Django setting 控制,默认为True
。
问题在于,当 CORS 执行预检请求时,它可以确定是否可以发出请求,在请求的 URL 处必须有一个有效的响应。因为您正在重定向请求,所以预检请求失败并且您在没有信息的情况下陷入困境。
您可以通过在代码中添加尾部斜杠来解决此问题。似乎有几个solutions for doing this with ext,但我个人不能推荐一个具体的。您还可以手动设置 url 以使用尾部斜杠,这听起来就像您之前所做的那样。
或者你可以使用 JSONP...
您找到了替代解决方案,即使用 JSONP 发出请求,而不是依赖 CORS。这解决了预检问题,适用于所有主要浏览器,但有一些缺点需要考虑。环顾四周,您可以找到更多information on CORS vs JSONP。
如果您想将任何更改推送到您的 API,您将需要 CORS,因为 JSONP 仅支持 GET
请求。 CORS 还有其他优点,例如中止请求的能力。
【讨论】:
非常好的解释谢谢。对于这种特殊情况 GET 操作就足够了,但在稍后阶段我可能想使用其他东西,所以这个回复特别有用。以上是关于更改商店的 URL 时,ExtJS 5 应用程序 + Django 休息框架 CORS 错误的主要内容,如果未能解决你的问题,请参考以下文章
Extjs 同步商店给了我一个 url is undefined 错误在特定条件下
EXTJS 5.0:无限网格滚动不适用于商店中的 extraParams