一:
from django.views.decorators.csrf import csrf_exempt
# 获取微信返回的code信息 @csrf_exempt def wechat_auth(req): if req.method == 'POST': code = req.POST.get('code') data_info = get_access_token_info(code) return JsonResponse({'message': data_info, "status": '1'}) return JsonResponse({'message': '扫码失败,请刷新重试!',"status": 0})
scrf_exempt是用来解决视图可以进行跨域请求。
1:什么是跨域请求呢?
假如: 在http:www.aa:8080/index.html里面的js代码发起了http:api:aa:9999/index_data这个地址的请求。 那么: 我们是得不到数据的? 为什么得不到数据呢? 原因:浏览器不要这个数据
理解:跨域不是服务器不给数据,也不是浏览器发现了跨域,不进行了请求。
解决:同源策略是浏览器的策略,和服务器没有关系,不过我们可以通过对服务器的响应头配置,让浏览器接收这次数据(后端解决办法)
例子:
服务器
from flask import Flask from flask import make_response from flask import render_template app = Flask(__name__) # 服务器代码 @app.route("/index_data", methods=["GET"]) def test1(): print("服务器接收了这次请求") response = make_response("hello world") return response if __name__ == '__main__': app.run(debug=True,host="0.0.0.0",port=9999)
# 端口为9999的服务器
# 后端 from flask import Flask from flask import render_template app = Flask(__name__) @app.route("/index", methods=["GET"]) def test1(): return render_template("csrf_test.html") if __name__ == '__main__': app.run(debug=True) # 前端 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="/static/jquery-1.12.4.min.js"></script> <script> $(function () { $("#btn").click(function () { $.ajax({" url:"http://127.0.0.1:9999/index_data", #从 http:127.0.0.1:5000/index的域向http:127.0.0.1:9999/index_data的域发送请求 type:"get", success:function (dat) { console.log(dat) } }) }) }) </script> </head> <body> <input type="submit" value="点我试试" id="btn"> </body> </html> # 前端运行
解决:服务器响应的时候,给请求头加入Acess-Control-Allow-Origin参数:值为:http://127.0.0.1:5000 就可以解决从5000端口向9999端口要数据的情况。
from flask import Flask from flask import make_response from flask import render_template app = Flask(__name__) # 服务器代码 @app.route("/index_data", methods=["GET"]) def test1(): print("服务器接收了这次请求") response = make_response("hello world") response.headers["Access-Control-Allow-Origin"] = "http://127.0.0.1:5000" # 服务器告诉浏览器,允许5000端口进行数据传输。 return response if __name__ == '__main__': app.run(debug=True,host="0.0.0.0",port=9999)
5000端口运行的结果:
同源策略:同协议、同域名、同端口
结论:服务器通过响应头设置:跨域浏览器的host:port,保证跨域浏览器的能够顺利的拿到服务器的数据。
二:浏览器的请求头中
更复杂的跨区请求:浏览器还会先发送options请求,然后在发送正常的get请求,因此还要对response.headers中添加更过的字段
# TODO 后面会进行测试。
三:django中的跨域请求的解决方法
方法一:普通的视图函数
# 获取微信返回的code信息 @csrf_exempt def wechat_auth(req): if req.method == 'POST': code = req.POST.get('code') data_info = get_access_token_info(code) return JsonResponse({'message': data_info, "status": '1'}) return JsonResponse({'message': '扫码失败,请刷新重试!',"status": 0})
方法二:继承视图类的类视图
from django.views.decorators.csrf import csrf_exempt class MyView(View): def get(self, request): return HttpResponse("hi") def post(self, request): return HttpResponse("hi") @csrf_exempt def dispatch(self, *args, **kwargs): return super(MyView, self).dispatch(*args, **kwargs)
方法三:在urls.py中设置
from django.conf.urls import url from django.views.decorators.csrf import csrf_exempt import views urlpatterns = [ url(r'^myview/$', csrf_exempt(views.MyView.as_view()), name='myview'), ]