Django之Ajax传输数据

MTV与MVC模型

MTV与MVC都是模型,只不过MTV是django自己定义的,具体看一下他们的意思

MTV模型(django)

M:模型层(models.py)

T:templates文件夹

V:视图层(views)

MVC模型

M:模型层

V:视图层(views.py)

C:控制器(Controller) urls.py

总结:本质上django的MTV也是MVC

前后端传输数据编码格式

首先,在我们不指定传输数据的时候,默认的contentType都是urlencoded

urlencoded

  对应的数据格式:name=jason&password=555

  后端获取数据:request.POST  

  PS:django会将urlencded编码的数据解析自动放到request.POST

formdata

  form表单传输文件的编码格式

  后端获取文件格式数据:request.FILES

  后端获取普通键值对数据:request.POST

application/json 

  form表单不支持,Ajax支持

  Ajax发送json格式数据

  需要注意的点

    编码与数据格式要一致

 

Ajax(重点掌握)

 

Ajax支持异步提交数据,局部刷新页面,这种情况我们在好多页面都会看到,那我们要如何做到呢?先来学习Ajax的基础语法~~~记住四兄弟即可

 

提交的地址(url):控制数据的提交地址,不写默认往当前位置提交

 

提交的方式(type):默认是get,要将get请求换成post

 

提交的数据(data):类似于字典的格式,字典具有一一标识的优点

 

回调函数(success):function(data){}data接收到的后端传输的数据

 

基本结构如下:

 

<script>  //记得写在html页面的最下方或者是你写在js里面,然后引入
    $('绑定事件的id').click(function () {   //给你要让Ajax触发的按钮绑定一个事件
        $.ajax({                          //Ajax的固定写法,在{}里面写你的四兄弟
            url:'在这里写你的提交的路径',     //不写默认是当前页面提交
            type:'post' ,                 //将请求方式从默认的get改成post
            data:{},                      //这个固定是data,后面放的是字典的形式
            success:function (data) {     //回调函数,拿到的是提交过后的数据,就是后端处理过后的数据,不要忘记参数,这个参数就是接收后端处理过后的数据
                //对接受到的数据进行处理,做的是局部刷新操作
          alert(123)
} }) }) </script>

 

自己尝试着写一个不跳转的动态页面,比如1+1=2

Ajax实现简单版页面局部刷新

我们首先需要的就是自己定义三个input框,然后动态获取到前两个框中的值,通过Ajax放到第三个input框中,代码演示如下

<input type="text" id="i1" >+<input type="text" id="i2" >=<input type="text" id="i3">
<button id="b1">点我点我</button>


<script>
$('#b1').click(function () {
    $.ajax({
        url:'/index/',
        type:'post',
        data:{'i1':$('#i1').val(),'i2':$('#i2').val()},
        success:function (data) {
            
            $('#i3').val(data)

        }
    })
})
</script>
html展示

后端数据处理

def index(request):
    if request.method=='POST':
        i1=request.POST.get('i1')
        i2=request.POST.get('i2')
        print(i1,i2)
        res=int(i1)+int(i2)
        print(res,type(res))
        return HttpResponse(res)
    return render(request,'index.html')
views展示

注意:Ajax不要与form表单联合使用,直接使用input框就可以

Ajax实现json格式数据的传输

 

具体代码展示如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
<p>username:<input type="text" id="u1"></p>
<p>password:<input type="password" id="p1"></p>
<button id="b1">提交</button>
<input type="text" id="i1">

<script>
    $('#b1').click(function () {
        $.ajax({
            url:'',
            type:'post',
            contentType:'application/json',
            data:JSON.stringify({
                'username':$('#u1').val(),
                'password':$('#p1').val()
            }),
            success:function (data) {
                $('#i1').val(data)

            }
        })
    })
</script>


</body>
</html>
json格式html展示
def jsonajax(request):
    print('method:', request.method)
    print('POST:', request.POST)
    print('GET:', request.GET)
    print('body:', request.body)
    if request.method=='POST':
        data=request.body
        import json
        res=data.decode('utf-8')
        print(res,type(res))
        res1=json.loads(res)
        print(res1,type(res1))
        return HttpResponse(res1)
    return render(request,'jsonajax.html')
views展示

Ajax实现文件上传

  1.利用一个js内置对象FormData

  2.这个FormData即可以传普通的键值对也可以传文件

  3.需要修改两个默认的参数processData,contentType

  4.获取input框存储的文件数据$('input')[0].files[0]

def fileupload(request):

    if request.method=='POST':
        print(request.POST)
        print(request.FILES)

        return HttpResponse('收到了,小老弟')
    return render(request,'fileupload.html')
Ajax实现文件上传views展示
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
    <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
</head>
<body>
文件上传:<input type="file" id="i1">
<button id="b1">点击提交</button>
<script>
    $('#b1').click(function () {
       //传文件的时候在form表单中我们需要制定参数是formdata,在这里我们也要来一个formdata
        let formdata = new FormData();
        // formData对象不仅可以传文件而且可以传普通的键值对
        formdata.append('name','jason');
        //获取input框存放的文件
        //这里就用到了files这个方法,jquery是没有这个方法的,所以我们要先得到一个js对象
        //$('#i1')[0].files[0]  是因为files里面有好多个文件,而我们只要第一个
        formdata.append('myfile',$('#i1')[0].files[0]);
        $.ajax({
           url:'',
           type:'post',
           data:formdata,
           //ajax发送文件需要修改两个固定的参数
           processData:false,  //告诉浏览器不要对数据进行处理
           contentType:false,  //告诉浏览器使用自带的formdata格式,不要编码
           //回调函数
           success:function (data) {
               alert(data)
           }

        })
    })
</script>
</body>
</html>
Ajax实现文件上传html展示

总结:Ajax的特点是异步提交数据,产生局部刷新的效果,默认提交数据的方式是get提交,所以我们需要修改里面的type类型,然后我们还可以自定义FormData对象,Ajax也支持基于这个对象的大文件上传。

Ajax和form表单的区别:

1.form表单不支持异步提交局部刷新

2.form表单不支持传输json格式数据

3.form表单与Ajax默认传输数据的编码格式都是urlencoded

 

 

小结:基于现在所学,前端向后端发请求的方式有如下几种

1.浏览器窗口手动输入网址     get请求

2.a标签的href属性                  get请求

3.form表单                              get/post请求

4.Ajax                                     get/post请求

其中,form表单和Ajax默认请求都是get

批量插入数据

当你打开一个页面的时候,想要直接插入100条数据到数据库,然后直接展示到前端页面上来,如何做到?那还不简单,我可以直接for循环100条数据,然后插入数据库,最后在从数据库中查出来展示,上代码!

def insernum(request):
    #动态插入100条数据
    for i in range(100):
        models.Num.objects.create(name='第%s本书'%i)
    #查询所有的书籍展示到前端
    book_list = models.Num.objects.all()
    return render(request,'num.html',locals())

但是,我们这样子做到话,效果真的超级超级的低,前端页面一直在等待我们数据的插入,虽然实现了数据的插入和展示,但是效率太低,那我们就得用到一个新的方法,我们先生成1000个数据对象,不走数据库,速度是很快的,然后将这1000个数据对象一次性插入,django支持我们这么做,用的是bulk_creat(),批量插入数据,见代码

def booklist(request):
    l=[]  #数据太大的话,能不能做成生成器,每次只有一点****
    for i in range(10000):
        l.append(models.Book2(name='第%s本书'%i))  生成了一个对象
    models.Book2.objects.bulk_create(l)  批量插入数据,速度超级快

  
  g=(=models.Book2(name = '%s'%i)for i in range(100000000))***
  
  models.Book2.objects.bulk_create(l)

 

自定义分页器

首先我们要先导入一个类,这个类可以帮我们实现分页的功能,将这个导入的文件放在utils里面,在下面新建一个py文件,你得给人家一个家不是吗!

class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        """
        封装分页相关数据
        :param current_page: 当前页
        :param all_count:    数据库中的数据总条数
        :param per_page_num: 每页显示的数据条数
        :param pager_count:  最多显示的页码个数

        用法:
        queryset = model.objects.all()
        page_obj = Pagination(current_page,all_count)
        page_data = queryset[page_obj.start:page_obj.end]
        获取数据用page_data而不再使用原始的queryset
        获取前端分页样式用page_obj.page_html
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1

        if current_page < 1:
            current_page = 1

        self.current_page = current_page

        self.all_count = all_count
        self.per_page_num = per_page_num

        # 总页码
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager

        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)

    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num

    @property
    def end(self):
        return self.current_page * self.per_page_num

    def page_html(self):
        # 如果总页码 < 11个:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 总页码  > 11
        else:
            # 当前页如果<=页面上最多显示11/2个页码
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1

            # 当前页大于5
            else:
                # 页码翻到最后
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1

        page_html_list = []
        # 添加前面的nav和ul标签
        page_html_list.append('''
                    <nav aria-label='Page navigation>'
                    <ul class='pagination'>
                ''')
        first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
        page_html_list.append(first_page)

        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)

        page_html_list.append(prev_page)

        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)

        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)

        last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # 尾部添加标签
        page_html_list.append('''
                                           </nav>
                                           </ul>
                                       ''')
        return ''.join(page_html_list)
分页器

然后我们直接导入使用就可以了

    后端:
            book_list = models.Book2.objects.all()
            # 数据总条数
            all_count = book_list.count()
            # 当前页
            current_page = request.GET.get('page',1)
            # 实例一个分页器对象
            page_obj = my_page.Pagination(current_page=current_page,all_count=all_count)
            # 对总数据进行切片
            page_queryset = book_list[page_obj.start:page_obj.end]
        
        前端:
1.将book_list全部替换册灰姑娘book_queryset    
       2.渲染分页器样式
{{ page_obj.page_html
|safe }} # 帮你渲染的是带有bootstrap样式的分页器

django 自带的分页器,和我们差不多,就相当于每次手动写一遍

 

又是一个愉快的周末🙂🙂🙂

 

posted @ 2019-06-15 15:00  mcc61  阅读(2551)  评论(1编辑  收藏  举报