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之数据序列化(json、pickle、shelve)
Mar 30 Python
Python实现压缩和解压缩ZIP文件的方法分析
Sep 28 Python
Django进阶之CSRF的解决
Aug 01 Python
Centos部署django服务nginx+uwsgi的方法
Jan 02 Python
用python做游戏的细节详解
Jun 25 Python
Python实现个人微信号自动监控告警的示例
Jul 03 Python
python logging 日志的级别调整方式
Feb 21 Python
python获取栅格点和面值的实现
Mar 10 Python
pymysql之cur.fetchall() 和cur.fetchone()用法详解
May 15 Python
python七种方法判断字符串是否包含子串
Aug 18 Python
python全栈开发语法总结
Nov 22 Python
使用Djongo模块在Django中使用MongoDB数据库
Jun 20 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
几种显示数据的方法的比较
2006/10/09 PHP
PHP5 安装方法
2007/01/15 PHP
php读取文件内容至字符串中,同时去除换行、空行、行首行尾空格(Zjmainstay原创)
2012/07/31 PHP
基于php 随机数的深入理解
2013/06/05 PHP
浅析51个PHP处理字符串的函数
2013/08/02 PHP
ThinkPHP的L方法使用简介
2014/06/18 PHP
Yii2中datetime类的使用
2016/12/17 PHP
javascript 禁止复制网页
2009/06/11 Javascript
js中将HTMLCollection/NodeList/伪数组转换成数组的代码
2011/07/31 Javascript
JS分页效果示例
2013/10/11 Javascript
jQuery:delegate中select()不起作用的解决方法(实例讲解)
2014/01/26 Javascript
遍历DOM对象内的元素属性示例代码
2014/02/08 Javascript
详解JS函数重载
2014/12/04 Javascript
AngularJS定时器的使用与移除操作方法【interval与timeout】
2016/12/14 Javascript
Vue实现动态显示textarea剩余字数
2017/05/22 Javascript
vue-cli的eslint相关用法
2017/09/29 Javascript
详解自定义ajax支持跨域组件封装
2018/02/08 Javascript
vue init webpack myproject构建项目 ip不能访问的解决方法
2018/03/20 Javascript
Vuex 使用及简单实例(计数器)
2018/08/29 Javascript
微信小程序实现左右列表联动
2020/05/19 Javascript
inquirer.js一个用户与命令行交互的工具详解
2019/05/18 Javascript
详解Python编程中time模块的使用
2015/11/20 Python
Python学习_几种存取xls/xlsx文件的方法总结
2018/05/03 Python
利用Pandas读取文件路径或文件名称包含中文的csv文件方法
2018/07/04 Python
Python 16进制与中文相互转换的实现方法
2018/07/09 Python
Python之inspect模块实现获取加载模块路径的方法
2018/10/16 Python
Django1.11自带分页器paginator的使用方法
2019/10/31 Python
Pandas实现dataframe和np.array的相互转换
2019/11/30 Python
appium+python adb常用命令分享
2020/03/06 Python
python实现简单文件读写函数
2021/02/25 Python
使用html2canvas实现浏览器截图的示例代码
2018/01/26 HTML / CSS
学生党员思想汇报
2013/12/28 职场文书
中专毕业生的自荐书
2014/07/01 职场文书
六年级上册《闻官军收河南河北》的教学设计
2019/11/15 职场文书
Python实现学生管理系统(面向对象版)
2021/06/24 Python
swagger如何返回map字段注释
2021/07/03 Java/Android