Django ajax 技术总结

django ajax 可能用到的技术细节我们来做个总结。

软件环境

软件版本
python3.6.6
django2.0
jquery1.8.3

技术注意点:

  • 小样板 Example
  • csrf 解决方案
  • python 序列化对象
  • js 端如何使用对象
  • 补不足

小样板Example

urls.py

urlpatterns = [
    ....,
    url(r'^author/save/$',   book_views.author_save)
]

views.py

from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def author_save(request):

    if request.method == "POST":
        authorName = request.POST.get('authorName', None)
        authorAge  = request.POST.get('authorAge', 20)
        print("author %s %d" % (authorName, int(authorAge)))
        # return HttpResponse( json.dump({'new_author':new_author}) )
        author = Author()
        author.name = authorName
        author.age = int(authorAge)
        author.save()

    return HttpResponse( json.dumps( author, default=author2dict ) )

author_admin.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>作者管理</title>
    {% load static %}
    <script src="{% static 'js/jquery-1.8.3.min.js' %}"></script>
    <link href="{% static 'css/bookstyle.css' %}?v=2" type="text/css" rel="stylesheet"/>

</head>
<style>
#formDiv {
    margin-top:30px;
    margin-left:10px;
    overflow: hidden;
}
#formDiv *{
    float: left;
}
#formDiv > div{
    clear: both;
}

</style>
<body>

<div id="show">
   <ul>
       <li>
        <div>作者</div>
        <div>年龄</div>
       </li>
   </ul>
</div>

<div id="formDiv">
{% csrf_token %}
    <div><input type="text" name="authorName"/></div>
    <div><input type="text" name="authorAge"/></div>
    <div><button id="c2">提交</button></div>
</div>
<script type="text/javascript">
//jquery 方法
$(document).ready(function(){

    $('#c2').on('click', function(){

        var authorName = $('input[name=authorName]').val();
        var authorAge = $('input[name=authorAge]').val();
        console.log( "authorName: " + authorName);

        var data = {
                authorName: authorName,
                authorAge: authorAge
        };

        $.ajax({
                url: '/author/save/',
                type: 'post',
                data: data,
                async:true,
                csrfmiddlewaretoken:'{{ csrf_token }}',
                success: function (res) {
                    add2list(JSON.parse(res));
                    alert('作者添加成功')
                },
                error:function () {

                }
            });


    })

    var add2list = function(data){
        console.log(data.name)
        $('#show > ul').append('<li><div></div><div></div></li>')
        $('#show > ul > li:last > div:eq(0)').html(data.name)
        $('#show > ul > li:last > div:eq(1)').html(data.age)
    };
});
</script>
</body>
</html>

csrf 解决方案

CSRF(Cross-site request forgery跨站请求伪造),不同的语言框架, 解决方案比较多, 这是一种服务器端的, 访问安全协议。 这种危害性是比较大的, 网站的请求可能会被随意的使用和篡改。
一般服务器端默认会限制跨域的访问请求。django通过中间件来默认限制访问.

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

注意: ‘django.middleware.csrf.CsrfViewMiddleware’,

这个访问,默认会限制AJAX的请求, 也是比较麻烦, 所以
– 方案1 就是 去掉这个组件,
– 方案2 使用装饰器

from django.views.decorators.csrf import csrf_exempt
@csrf_exempt
def .....

– 方案3 (1,2)方案本质上都是关闭了csrf的限制, 如果一个请求是比较重要的,可以使用csrf_token 来实现csrf的客户端到服务器端的,验证请求。

<div id="formDiv">
{% csrf_token %}
</div>
<script>
        $.ajax({
                url: '/author/save/',
                type: 'post',
                data: data,
                async:true,
                csrfmiddlewaretoken:'{{ csrf_token }}',
                success: function (res) {
                    add2list(JSON.parse(res));
                    alert('作者添加成功')
                },
                error:function () {

                }
            });
// 或者使用一下代码

        $(function(){
            $.ajaxSetup({
                beforeSend: function(xhr,settings){
                    xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'));
                }
            });

            $('#btn1').click(function () {
                $.ajax({
                    url: '/login/',
                    type:"GET",
                    data: {'user': 'root', 'pwd': '123'},
                    // headers: {'X-CSRFtoken': $.cookie('csrftoken')},
                    success:function(arg){

                    }
                })
            });
        })
</script>


注意:
{% csrf_token %}
是通过settings.py 里的
SECRET_KEY = ‘tcyehgzal46yvsb_++zt&c-m+ozkm327a3xlwb+p%n2gp-v%*8’
加了一把salt 一起生成的心的token
会生成一个 这个值是服务器端的token 用来在前端生成后 交给服务器端验证
ajax提交的时候 csrfmiddlewaretoken:’{{ csrf_token }}’, 来提交数据
遗憾的是这个解决方案, 我在本地测试没通过, 可能是字符打错了, 这个大家可以继续尝试

这个问题解决了, 可以吧 {{ csrf_token }} 字段写在data属性里由ajax一起提交

python 序列化

python 默认可以使用 json.dumps(..) 来初始化 dict 对象, 但是对普通的object 对象序列化会直接报一个, [Python]json 错误xx is not JSON serializable 错误。 这个问题的详细叙述可以看一下廖雪峰关于序列化的详细解释 我就不重述了。
Anyway,从httpResponse传对象给 客户端的代码是


def author2dict(author):
    return { 'name': author.name,
             'age': author.age
             }

def author_save(request):

    if request.method == "POST":
        authorName = request.POST.get('authorName', None)
        authorAge  = request.POST.get('authorAge', 20)
        print("author %s %d" % (authorName, int(authorAge)))
        # return HttpResponse( json.dump({'new_author':new_author}) )
        author = Author()
        author.name = authorName
        author.age = int(authorAge)
        author.save()

    return HttpResponse( json.dumps( author, default=author2dict ) )

注意: 这里的Author 对象的定义是
class Author(models.Model):
name=models.CharField(max_length=20)
age=models.IntegerField()
book=models.ManyToManyField(Books) #book_id
这里的 book属性 我在上面
def author2dict(author):
return { ‘name’: author.name,
‘age’: author.age
}
并没有设置, 尝试了集中方式, 这个 如果大家有方案的话可以告诉我。

js 端如何使用对象

从服务端发出的 对象最后是以json格式传输的, 其实客户端拿到的就是一串字符串, 并不是json对象。 所以需要最后使用js 转义一下即可。

<script>
                success: function (res) {
                    add2list(JSON.parse(res));
                    alert('作者添加成功')
                },
</script>
最后就可以使用 res.name 的方式取出对象数据

补充不足

可以在views.py里 返回的时候直接使用JsonResponse 这样放回的就直接是
json格式了, 前端也不需要JSON.parse

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值