AJAX

ajax

  1. AJAX   JQuery

  2. AJAX csrftoken

  3. AJAX  request method

  4. AJAX  跨域

 

 

 

AJAX 是异步JavaScript 和xml

AJAX能实现在不重新加载真个网页的同时去更新部分网页

AJAX能实现异步更新,不需重新加载整个网页

XMLHttpRequest   是ajax 的基础

所有浏览器都支持XMLHttpRequest对象

创建XMLHttpRequest对象的方法

variable=new XMLHttpRequest()

老版本的 Internet Explorer (IE5 和 IE6)使用 ActiveX 对象:

variable=new ActiveXObject("Microsoft.XMLHTTP");

XMLHttpRequest用于和服务器进行交换数据
将请求发送给服务器



jQuery 发送ajax 的一些参数


http://www.w3school.com.cn/jquery/ajax_ajax.asp

contentType
类型 :'string'
默认值:"application/x-www-form-urlencoded" 发送数据给服务器时的内容编码类型
默认值适合大多数情况。如果你明确地传递了一个 content-type 给 $.ajax() 那么它必定会发送给服务器(即使没有数据要发送)。
如果想以其他方式提交数据, 比如contentType:"application/json",即向服务器发送一个json字符串
  data:JSON.stringify({
                       a:22,
                       b:33
                   }),
                   contentType:"application/json",
                   type:"POST",
             
               });                          //{a: 22, b: 33}

             注意:contentType:"application/json"一旦设定,data必须是json字符串,不能是json对象


######################------------traditional---------################

traditional:一般是我们的data数据有数组时会用到 :data:{a:22,b:33,c:["x","y"]},
              traditional为false会对数据进行深层次迭代;  
 


data:
类型:'string'
发送到服务器的数据。将自动转换为请求字符串格式。GET 请求中将附加在 URL 后。查看 processData 选项说明以禁止此自动转换。必须为 Key/Value 格式。
如果为数组,jQuery 将自动为不同值对应同一个名称。如 {foo:["bar1", "bar2"]} 转换为 '&foo=bar1&foo=bar2'。

datatype:
类型:'string'
预期服务器返回的数据类型
可用值:
  • ‘xml’
  • 'json'
  • 'html'
  • 'jsonp'
  • 'text'

from django.shortcuts import render,HttpResponse
from django.views.decorators.csrf import csrf_exempt
# Create your views here.

import json

def login(request):

    return render(request,'Ajax.html')


def ajax_get(request):

    l=['alex','little alex']
    dic={"name":"alex","pwd":123}

    #return HttpResponse(l)      #元素直接转成字符串alexlittle alex
    #return HttpResponse(dic)    #字典的键直接转成字符串namepwd
    return HttpResponse(json.dumps(l))
    return HttpResponse(json.dumps(dic))# 传到前端的是json字符串,要想使用,需要JSON.parse(data)

//---------------------------------------------------
    function testData() {

        $.ajax('ajax_get', {
           success: function (data) {
           console.log(data);
           console.log(typeof(data));
           //console.log(data.name);
           //JSON.parse(data);
           //console.log(data.name);
                                     },
           //dataType:"json",
                            }
                       )}
View Code

 


注解:Response Headers的content Type为text/html,所以返回的是String;但如果我们想要一个json对象 设定dataType:"json"即可,相当于告诉ajax方法把服务器返回的数据转成json对象发送到前端.结果为object 当然, return HttpResponse(json.dumps(a),content_type="application/json") 这样就不需要设定dataType:"json"了。 content_type="application/json"和content_type="json"是一样的!

type:

类型'string'

  • get
  • post
  • put
  • delete

url

类型'string'

 

回调函数

beforeSend

在发送请求之前调用,并且传入一个 XMLHttpRequest 作为参数。

success

当请求之后调用。传入返回后的数据,以及包含成功代码的字符串。

error

在请求出错时调用。传入 XMLHttpRequest 对象,描述错误类型的字符串以及一个异常对象(如果有的话)

complete

当请求完成之后调用这个函数,无论成功或失败。传入 XMLHttpRequest 对象,以及一个包含成功或错误代码的字符串



$.ajaxSetup({
name:value,
name:value,
})
Set default values for future Ajax requests. Its use is not recommended.
为将来的ajax请求设置默认值,不推荐使用



关于django csrftoken
官网链接:https://docs.djangoproject.com/en/1.11/ref/csrf/
如何使用


1 在middleware 中间,配置上'django.middleware.csrf.CsrfViewMiddleware
2 如果不使用中间件(不推荐),也可以使用csrf_protect()加到特定的views 上,
3在使用post form 的模板中,将 csrf_token 加到form 元素里面,如果这个form 用于内部的url
eg:
<form action="" method="post">{% csrf_token %}

 


If your view is not rendering a template containing the csrf_token template tag,
Django might not set the CSRF token cookie. This is common in cases where forms
are dynamically added to the page. To address this case, Django provides a view
decorator which forces setting of the cookie: ensure_csrf_cookie().

如果你的view 渲染的模板中没有包含csrf_token 模板标签,django 可能不会设置csrf token cookie,
这在一些form 被动态添加到页面中例子中是常见的。为了解决这个问题,django 提供了视图装饰器,ensure_csrf_cookies()强制设置cookie

AJAX

While the above method can be used for AJAX POST requests, it has some inconveniences: you have to remember to pass the CSRF token in as POST data with every POST request. For this reason, there is an alternative method: on each XMLHttpRequest, set a custom X-CSRFToken header to the value of the CSRF token. This is often easier, because many JavaScript frameworks provide hooks that allow headers to be set on every request.

First, you must get the CSRF token. How to do that depends on whether or not the CSRF_USE_SESSIONS setting is enabled.



如果CSRF_USE_SESSION 是True,需要token

如果你让CSRF_USE_SESSION 活动,你必须将token包含在html中,并用js 从DOM 将token 读取出来。
{% csrf_token %}
<script type="text/javascript">
// using jQuery
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
</script>

 


将token 设置到ajax 请求中在我目前理解有两种方式,
第一种是将token放到post data里
  将form 隐藏的标签name=csrfmiddlewaretoken 的val取到。

当html 表单中没有csrf_token 就需要使用第二种
,第二种是在xml http request 设置请求头,如下所示
这种方式要导入
js文件下载链接 https://github.com/js-cookie/js-cookie/
<script src="/static/js/jquery.cookie.js"></script>

 

    // 全局的ajax
   function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
            }
        }
    });

 

 

 

除了使用csrfmiddleware  作为整体的保护,也可以使用csrf_protect  装饰器,和中间件有相同的作用。

csrf_protect(view)

from django.views.decorators.csrf import csrf_protect
from django.shortcuts import render

@csrf_protect
def my_view(request):
    c = {}
    # ...
    return render(request, "a_template.html", c)

 

ensure_csrf_cookie(view)
This decorator forces a view to send the CSRF cookie


csrftoken是如何工作的。
cookie 是基于随机加密的value,其他站点无法访问到它。cookie 由CsrfViewMiddleware设置,这个cookie还加了salt
安全起见,每次用户登录的时候,secret的value都会改变。
2 form 隐藏的字段‘csrfmiddlewaretoken’这个字段的值也是secret 的value, 也加上了salt,在每次调用got_token() ,这个salt 都会更新,因此在每次响应,salt都会发生改变。
这部分是由模板标签来做的。
3对于到来的请求,除了HTTP GET, HEAD, OPTIONS or TRACE,csrf cookie 必须要有,并且csrfmiddlewaretoken也要存在,并且是正确的,如果不是会403 forbidden
When validating the ‘csrfmiddlewaretoken’ field value, only the secret, not the full token, is compared with the secret in the cookie value.

Page uses AJAX without any HTML form

A page makes a POST request via AJAX, and the page does not have an HTML form with a csrf_token that would cause the required CSRF cookie to be sent.

Solution: use ensure_csrf_cookie() on the view that sends the page.

当一个页面通过ajax发送post请求,并且这个页面没有带csrf_token 的html form,将会引起需要csrf cookie 的结果,

 

 

ajax发送请求的四种方法:

  •   post
  •        get
  •   delete
  •   put

对于使用ajax发送数据总结常用几种格式: 

   1字典形式     比如{'name':'wanger','age':20}

 2字典里有列表   {

        'name':'yuyang',

        'kecheng':['yuwen','shuxue']

          }

这种可以在$.ajax()里设置参数      traditional:true

3  字典里套字典     这种一般设置contentType:'application/json'

html

    $('#id-btn').click(function (e) {
       $.ajax({
        url:'/ajax/',
        type:'POST',
        contentType:'application/json',
        data:JSON.stringify(a),
           dataType:'json',
            success:function (data) {
            console.log(data);
        }

    })
    });

 

views后面要用request.body取到,取到的是bytes类型。

get

    $('#id-btn').click(function (e) {
       $.ajax({
        url:'/ajax/',
        type:'get',
{#        contentType:'application/json',#}
{#        data:JSON.stringify(a),#}
          data:{'book_id':'于洋'},
           dataType:'json',

            success:function (data) {
            console.log(data);
        }

    })
    });

 

view

        if request.is_ajax():
            print(request.path_info)
            print(request.GET.get('book_id'))

 

结果

/ajax/
于洋
[13/Nov/2017 18:17:46] "GET /ajax/?book_id=%E4%BA%8E%E6%B4%8B HTTP/1.1" 200 2379

 

delete

put 

首先判断request.method   

delete 和 put发送的数据都在request.body里

 

格式为b'k=v&k=v'当(contentType 是application/x-www-form-urlencoded)

 

 

如果想转为字典,可以这样操作,

 from django.http import QueryDict
 resp = request.body.decode('utf-8')
 s = QueryDict(resp)
 print(s.get('book_id'))
 from django.http import QueryDict
 resp = request.body.decode('utf-8')
 s = QueryDict(resp)
 print(s.get('book_id'))

 

关于QueryDict 对象

链接

https://docs.djangoproject.com/en/1.11/ref/request-response/

QueryDict常用方法

n an HttpRequest object, the GET and POST attributes are instances of django.http.QueryDict

在httprequest对象,GET 和POST属性是django.http.QueryDict的实例。

QueryDict实现了标准字典的方法,因为是字典的子类

>>> QueryDict('a=1&a=2&c=3')
<QueryDict: {'a': ['1', '2'], 'c': ['3']}>

 



>>> q = QueryDict('a=2&b=3&b=5')
>>> q.urlencode()
'a=2&b=3&b=5'

 


 



 AJAX 跨域jsonp 和 CORS

浏览器不允许

 

 jsonp

转自 https://www.cnblogs.com/dowinning/archive/2012/04/19/json-jsonp-jquery.html

jsonp其实与ajax并无多大关系,jsonp实际是用了像img,script这些标签的  src属性

使用jsonp要和远程约定好回调函数名字

jsonp只能get请求,没有post请求

 CORS

 

 阮一峰博客

CORS  跨站资源共享 scross origin resource share

http://www.ruanyifeng.com/blog/2016/04/cors.html

 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

 

实现cors通信的关键是服务器,只要CORS实现了CORS接口,就能跨源通信。

浏览器将请求分为两种:简单请求和非简单请求。

1) 请求方法是以下三种方法之一:

  • HEAD
  • GET
  • POST

(2)HTTP的头信息不超出以下几种字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

 

 

 

 

 






posted @ 2017-08-30 18:31  dragonbird  阅读(172)  评论(0编辑  收藏  举报