Python的Django应用程序解决AJAX跨域访问问题的方法


Posted in Python onMay 31, 2016

引子
使用Django在服务器端写了一个API,返回一个JSON数据。使用Ajax调用该API:

<!DOCTYPE HTML>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"/>
  <title>test</title>
</head>
<body>
<button onclick="showPersonInfo()">点我获取数据</button>
</body>
<script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script>
  <script>
    function showPersonInfo(){
      $.getJSON(
        'http://xxx/account/getuserinfo/',
        {username: "abc"},
        function(json) {
          var html='<br>'+'用户名:'+json.username+'<br>'+'姓:'+json.first_name+'<br>'+'名:'+json.last_name+'<br>'+'邮箱'+json.email;    
          document.write(html);
        }
      )
    }
  </script>
</html>

但是,Chrome浏览器提示错误:

No 'Access-Control-Allow-Origin' header is present on the requested resource.

经过一番Google发现这个问题是——CORS导致的。

什么是CORS?
CORS(跨域资源共享,Cross-Origin Resource Sharing)是一种跨域访问的机制,可以让Ajax实现跨域访问。
其实,在服务器的response header中,加入“Access-Control-Allow-Origin: *”即可支持CORS,非常的简单,apache/nginx等怎么配置,见参考文档。
举个例子:

  • API部署在DomainA上;
  • Ajax文件部署在DomainB上,Ajax文件会向API发送请求,返回数据;
  • 用户通过DomainC访问DomainB的Ajax文件,请求数据

以上过程就发生了跨域访问。如果直接使用Ajax来请求就会失败,就像Chrome提示的:

No 'Access-Control-Allow-Origin' header is present on the requested resource.

如何解决Ajax跨域访问问题?
解决跨域问题,有两个方法:1.使用jsonp 2.使CORS生效
使用jsonp方法,需要让服务器端放回jsonp格式的response,如Django可以加jsonp相关的decorator,如:https://coderwall.com/p/k8vb_a/returning-json-jsonp-from-a-django-view-with-a-little-decorator-help由于我不太喜欢这种方式,所以这里略过了,可看后面的参考资料。
使用CORS:这个用起来比较方便,现在大多数浏览器都支持了,且我web服务器完全开放给别人调用,所以比较推荐CORS。
1.使用JSONP
使用Ajax获取json数据时,存在跨域的限制。不过,在Web页面上调用js的script脚本文件时却不受跨域的影响,JSONP就是利用这个来实现跨域的传输。因此,我们需要将Ajax调用中的dataType从JSON改为JSONP(相应的API也需要支持JSONP)格式。
JSONP只能用于GET请求。

2.直接修改Django中的views.py文件
修改views.py中对应API的实现函数,允许其他域通过Ajax请求数据:

def myview(_request):
  response = HttpResponse(json.dumps({"key": "value", "key2": "value"}))
  response["Access-Control-Allow-Origin"] = "*"
  response["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS"
  response["Access-Control-Max-Age"] = "1000"
  response["Access-Control-Allow-Headers"] = "*"
  return response

3.安装django-cors-headers
这里还有一各发现!在Django中,有人开发了CORS-header的middleware,只在settings.py中做一些简单的配置即可,见:https://github.com/ottoyiu/django-cors-headers/现在用起来服务器端完全开放,开启CORS,没有跨域烦恼,真爽!~
安装django-cors-headers:

pip install django-cors-headers

在settings.py中增加:

INSTALLED_APPS = (
  ...
  'corsheaders',
  ...
)

...

MIDDLEWARE_CLASSES = (
  ...
  'corsheaders.middleware.CorsMiddleware',
  'django.middleware.common.CommonMiddleware',
  ...
)

可以配置允许跨域访问的白名单或者直接设置为允许所有的跨域访问,具体的配置可以看看他们的github页说明。

Python 相关文章推荐
Python中的zip函数使用示例
Jan 29 Python
在Python中操作列表之list.extend()方法的使用
May 20 Python
Python中atexit模块的基本使用示例
Jul 08 Python
Python入门学习之字符串与比较运算符
Oct 12 Python
Python 中 Meta Classes详解
Feb 13 Python
python多进程使用及线程池的使用方法代码详解
Oct 24 Python
python3.6 tkinter实现屏保小程序
Jul 30 Python
PyQt Qt Designer工具的布局管理详解
Aug 07 Python
pycharm中import呈现灰色原因的解决方法
Mar 04 Python
django 装饰器 检测登录状态操作
Jul 02 Python
java关于string最常出现的面试题整理
Jan 18 Python
Python实现简单的2048小游戏
Mar 01 Python
python语言使用技巧分享
May 31 #Python
Windows中安装使用Virtualenv来创建独立Python环境
May 31 #Python
Windows下Python使用Pandas模块操作Excel文件的教程
May 31 #Python
深入理解python中的浅拷贝和深拷贝
May 30 #Python
浅谈Python的文件类型
May 30 #Python
python中string模块各属性以及函数的用法介绍
May 30 #Python
Python 常用string函数详解
May 30 #Python
You might like
PHP常用代码
2006/11/23 PHP
fleaphp crud操作之findByField函数的使用方法
2011/04/23 PHP
PHP 自定义错误处理函数的使用详解
2013/05/10 PHP
PHP检测字符串是否为UTF8编码的常用方法
2014/11/21 PHP
[原创]php使用curl判断网页404(不存在)的方法
2016/06/23 PHP
php实现微信支付之退款功能
2018/05/30 PHP
在Javascript里访问SharePoint列表数据的实现方法
2011/05/22 Javascript
弹出最简单的模式化遮罩层的js代码
2013/12/04 Javascript
js中数组(Array)的排序(sort)注意事项说明
2014/01/24 Javascript
对js关键字命名的疑问介绍
2014/04/25 Javascript
使用JS+plupload直接批量上传图片到又拍云
2014/12/01 Javascript
js实现点击图片自动提交action的简单方法
2016/10/16 Javascript
vue.js 初体验之Chrome 插件开发实录
2017/05/13 Javascript
关于vue单文件中引用路径的处理方法
2018/01/08 Javascript
小程序实现列表删除功能
2018/10/30 Javascript
Vue 实现前进刷新后退不刷新的效果
2019/06/14 Javascript
layui异步加载table表中某一列数据的例子
2019/09/16 Javascript
详解微信小程序工程化探索之webpack实战
2020/04/20 Javascript
详解vue 组件注册
2020/11/20 Vue.js
[01:00:06]加油DOTA_EP01_网络版
2014/08/09 DOTA
[43:32]Winstrike vs VGJ.S 2018国际邀请赛淘汰赛BO3 第一场 8.23
2018/08/24 DOTA
Python的gevent框架的入门教程
2015/04/29 Python
Python多线程实现同步的四种方式
2017/05/02 Python
python验证码识别的示例代码
2017/09/21 Python
Django项目实战之用户头像上传与访问的示例
2018/04/21 Python
对python文件读写的缓冲行为详解
2019/02/13 Python
简单了解python shutil模块原理及使用方法
2020/04/28 Python
Python实现JS解密并爬取某音漫客网站
2020/10/23 Python
Python环境配置实现pip加速过程解析
2020/11/27 Python
如何打开WebSphere远程debug
2014/10/10 面试题
J2EE包括哪些技术
2016/11/25 面试题
考试没考好检讨书
2014/01/31 职场文书
学习十八大坚定理想信念心得体会
2014/03/11 职场文书
预备党员考察意见范文
2015/06/01 职场文书
2016婚礼主持词开场白
2015/11/24 职场文书
详解Go语言中配置文件使用与日志配置
2022/06/01 Golang