Django之JSON、AJAX、django内置序列化器、批量插入数据及分页器组件

1、JSON

1.1、定义
  • JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
  • JSON 是轻量级的文本数据交换格式
  • JSON 独立于语言
  • JSON 具有自我描述性,更易理解

JSON 使用 JavaScript 语法来描述数据对象,但是 JSON 仍然独立于语言和平台,JSON 解析器和 JSON 库支持许多不同的编程语言
在这里插入图片描述

1.2、合格的json对象(json只认双引的字符串格式)
["one", "two", "three"]
{ "one": 1, "two": 2, "three": 3 }
{"names": ["张三", "李四"] }
[ { "name": "张三"}, {"name": "李四"} ] 
1.3、不合格的json对象
{ name: "张三", 'age': 32 }  // 属性名必须使用双引号
[32, 64, 128, 0xFFF] // 不能使用十六进制值
{ "name": "张三", "age": undefined }  // 不能使用undefined
{ "name": "张三",
  "birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
  "getName":  function() {return this.name;}  // 不能使用函数和日期对象
}
1.4、stringify与parse方法

JavaScript中关于JSON对象和字符串转换的两个方法

1.4.1、JSON.parse()

用于将一个 JSON 字符串转换为 JavaScript 对象(json只认双引的字符串格式)

JSON.parse('{"name":"allen"}');
JSON.parse('{name:"allen"}') ;   // 错误
JSON.parse('[18,undefined]') ;   // 错误
1.4.2、JSON.stringify()

用于将 JavaScript 值转换为 JSON 字符串

JSON.stringify({"name":"allen"})

2、AJAX

2.1、定义

AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”,即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)
AJAX 不是新的编程语言,而是一种使用现有标准的新方法
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行

  • 异步 Javascript 和 XML
  • 异步:跟同步是对应的
  • javascript:通过javascript来操作,发送请求 ,到服务端
  • xml:数据交互使用xml,现在主流使用json格式
  • xml:可阅读性比较高,解析复杂,占的空间大
2.2、交互方式
  • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求
2.3、AJAX的优点
  • AJAX使用JavaScript技术向服务器发送异步请求
  • AJAX请求无须刷新整个页面
  • 因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高

两个关键点:1、局部刷新,2、异步请求

2.4、案例

通过Ajax,实现前端输入两个数字和操作符号,服务器做运算,返回到前端页面

2.4.1、views.py
def calculate(request):
    if request.is_ajax():
        num1 = int(request.POST.get('num1'))
        num2 = int(request.POST.get('num2'))
        opt = request.POST.get('opt')
        if opt == '+':
            res = num1 + num2
        elif opt == '-':
            res = num1 - num2
        elif opt == '*':
            res = num1 * num2
        else:
            res = num1 / num2
        return HttpResponse(res)
    return render(request, 'calculate.html')
2.4.2、calculate.html
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<p>数字1: <input type="text" id="num1"></p>
<p>符号: <select name="" id="opt">
    <option value="+">+</option>
    <option value="-">-</option>
    <option value="*">*</option>
    <option value="/">/</option>
</select></p>
<p>数字2: <input type="text" id="num2"></p>

<p>结果: <input type="text" id="res" value=""></p>
<p>
    <button id="btn">提交</button>
</p>
<script src="/static/js/jquery/jquery-1.12.4.min.js"></script>
<script>
    $('#btn').on('click', function () {
        $.ajax({
            url: '',
            data: {'num1': $('#num1').val(), 'num2': $('#num2').val(), 'opt': $('#opt').val()},
            method: 'post',
            success: function (data) {
                $('#res').val(data)
            }
        });
    });
</script>
</body>
</html>
2.5、ajax上传文件
2.5.1、views.py
def index(request):
    if request.method == 'POST':
        username = request.POST.get('username')
        password = request.POST.get('password')
        files = request.FILES.get('filename')
        with open(r'{}'.format(files.name), mode='wb') as fp:
            for line in files.chunks():
                fp.write(line)
        print(username)
        print(password)
        return HttpResponse('上传成功')
    return render(request, 'index.html')
2.5.2、index.html
<h1>ajax上传头像提交数据</h1>
<form>
    <p>用户名: <input type="text" id="username"></p>
    <p>密码: <input type="password" id="password"></p>
    <p>头像: <input type="file" id="myfile"></p>
    <p><input type="button" id="btn" value="提交数据"></p>
</form>
2.5.3、js代码
<script>
$('#btn').on('click', function () {
    formdata = new FormData();  // 实例化得到一个fromdata对象
    datas = $('#myfile')[0].files[0];
    formdata.append('filename', datas);
    # fomdata现在只放了一个文件对象,也可以放数据
    formdata.append('username', $('#username').val());
    formdata.append('password', $('#password').val());
    $.ajax({
        url: '/ajax_file/',
        type: 'post',
        //上传文件必须写这两句话
        processData: false,  // 预处理数据
        contentType: false,  // 不指定编码,如果不写contentType,默认用urlencoded
        data: formdata,  // formdata内部指定了编码,并且自行处理数据
        // data: {'username':$('#username').val(),'password':$('#password').val()},
        success: function (data) {
            alert(data);
        }
    });
});
</script>
2.6、ajax提交json格式
2.6.1、views.py
def ajax_json(request):
    if request.is_ajax():
        data = request.body
        # data = request.POST  这里没有数据
        import json
        user_dict = json.loads(data.decode('utf-8'))
        print(user_dict, type(user_dict))
		dic = {'status': 100, 'msg': '成功'}
	# 方式一
	# return HttpResponse(json.dumps(dic))
	# 方式二
    return JsonResponse(dic)  # 内部设置了编码
2.6.2、index.html
<h1>通过ajax提交json格式数据</h1>
<p>用户名:<input type="text" id="id_name1"></p>
<p>密码:<input type="text" id="id_password1"></p>
<p><button id="btn_json">提交</button></p>
2.6.3、js代码
$("#json_btn").on('click', function () {
    $.ajax({
        url: '/ajax_json/',
        method:'post',
        contentType: 'application/json',
        //data要是json格式字符串
        //data:'{"name":"","password":""}',
        //把字典转成json格式字符串
        //JSON.stringify(dic)
        //把json格式字符串转成对象
        //JSON.parse(data)
        data:JSON.stringify({username:$('#user').val(), password:$('#pwd').val()}),
        success:function(data){
        	// 返回字符串类型,需要转成js的对象,字典
			// 1、如果django 返回的是HttpResponse,data是json格式字符串,需要自行转成字典
            // 2、如果django 返回的是JsonResponse,data是就是字典
            // ajax这个方法做的是,如果响应数据是json格式,自动反序列化
            console.log(data);
            console.log(typeof data)
            var res=JSON.parse(data)
            console.log(typeof res)
            console.log(res.status)
            console.log(res.msg)
        }
    })
});

3、django内置序列化器

3.1、views.py
from django.core.serializers import serialize

def test_ser(request):
    ll = []
    book_list = Book.objects.all()
    # 方式一
    for book in book_list:
        ll.append({'name': book.name, 'price': str(book.price), 'publish_id': book.publish_id})
    ret = json.dumps(ll)
    
	# 方式二 (django内置序列化器)
    # ret = serialize('json',book_list)  # ret就是json格式字符串
    return HttpResponse(ret)

4、批量插入数据

def bulk_create_data(request):
	# 方式一
    for line in range(1, 101):
        Book.objects.create(name='图书%s' % line, price=line)
        
    # 方式二
    ll = []
    for line in range(1, 101):
        book_obj = Book(name='图书%s' % line, price=line)
        ll.append(book_obj)
    Book.objects.bulk_create(ll)
    return HttpResponse('批量插入成功')

5、分页器组件

在页面显示分页数据,需要用到Django分页器组件
from django.core.paginator import Paginator

5.1、分页器重要参数
Paginator对象:    paginator = Paginator(查询出来的数据, 10)
per_page   每页显示条目数量
count      数据总个数
num_pages  总页数
page_range 总页数的索引范围,如: (1,10),(1,200)

page:     page对象    
page对象:  page=paginator.page(1)
has_next              是否有下一页
next_page_number      下一页页码
has_previous          是否有上一页
previous_page_number  上一页页码
object_list           分页之后的数据列表
number                当前页
paginator             paginator对象

总结:
1、项目数据量大了以后,比如涉及到分页,一页一页的加载显示
2、django中分页器组件,把分页常用的东西,封装到一个类中
3、实例化得到一个对象,对象里有属性和方法

5.2、分页器的简单使用
5.2.1、Paginator对象的属性和方法
book_list = models.Book.objects.all()
# 实例化得到对象
# 第一个参数: 要分页的数据,book_list
# 第二个参数: 每页显示条数
paginator = Paginator(book_list,10)
# Paginator对象的属性和方法
print(paginator.per_page)  # 每页显示的条数
print(paginator.count)  # 总条数,总共要分页多少条数据
print(paginator.num_pages)  # 总页码数
print(paginator.page_range)  # 页码的生成器 [1,2,3,4,5,6,7,8,9,10]
5.2.2、Page对象的属性和方法
# Page类 的对象
page = paginator.page(2)   #  第二页的对象
# 每一页的对象,属性和方法
print(page.has_next())      # 有没有下一页
print(page.next_page_number())  # 下一页页码
print(page.has_previous())  # 是否有上一页
print(page.previous_page_number())  # 上一页页面 (当前页如果是第一页,没有上一页)
print(page.object_list)            # 当前页的所有数据
print(page.number)           # 当前页的页码数
5.2.3、指定表模型的排序字段及排序方式
class Meta:
     ordering=('id', )  # 默认以id排序
5.2.4、视图
def index(request):
    # 需要的第三个参数
    page_num_int = int(request.GET.get('page',1))
    book_list = models.Book.objects.all()
    paginator = Paginator(book_list, 10)

    # 需要的第一个参数: 页码的生成器 [1,2,3,4,5,6,7,8,9,10]
    page_range = paginator.page_range
    # 需要的第二个参数,获取某一页的page对象
    page = paginator.page(page_num_int)
    return render(request, 'index.html', {'page_range':page_range,'page':page,'page_num_int':page_num_int})
5.2.5、模板
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.min.css">
    <title>Title</title>
</head>
<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-6 col-md-offset-3">
            <table class="table">
                <thead>
                <tr>
                    <th>id</th>
                    <th>名字</th>
                    <th>价格</th>
                </tr>
                </thead>
                <tbody>
                {% for book in page.object_list %}
                    <tr>
                        <td>{{ book.id }}</td>
                        <td>{{ book.name }}</td>
                        <td>{{ book.price }}</td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>

            <div class="text-center">
                <nav aria-label="Page navigation">
                    <ul class="pagination">

                        {% if page.has_previous %}
                            <li>
                                <a href="/?page={{ page.previous_page_number }}" aria-label="Previous">
                                    <span aria-hidden="true">&laquo;</span>
                                </a>
                            </li>
                        {% else %}
                            <li class="disabled">
                                <a href="" aria-label="Previous">
                                    <span aria-hidden="true">&laquo;</span>
                                </a>
                            </li>
                        {% endif %}

                        {% for page_num in page_range %}
                            {% if page_num_int == page_num %}
                                <li class="active"><a href="/?page={{ page_num }}">{{ page_num }}</a></li>
                            {% else %}
                                <li><a href="/?page={{ page_num }}">{{ page_num }}</a></li>
                            {% endif %}

                        {% endfor %}

                        {% if page.has_next %}
                            <li>
                                <a href="/?page={{ page.next_page_number }}" aria-label="Next">
                                    <span aria-hidden="true">&raquo;</span>
                                </a>
                            </li>
                        {% else %}
                            <li class="disabled">
                                <a href="" aria-label="Next">
                                    <span aria-hidden="true">&raquo;</span>
                                </a>
                            </li>
                        {% endif %}
                    </ul>
                </nav>
            </div>
        </div>
    </div>
</div>
</body>
</html>
5.3、分页器的进阶使用
# 最多显示前5页、后5页和当前页,总共11个页码,如果少于11,全部显示出来

# 显示左5,右5,总共11个页,
# 1、如果总页码大于11
# 1.1、if 当前页码减5小于1,要生成1到12的列表(顾头不顾尾,共11个页码)
page_range=range(1,12)

# 1.2、elif 当前页码+5大于总页码,生成当前页码减10,到当前页码加1的列表(顾头不顾尾,共11个页码)
page_range=range(paginator.num_pages-10,paginator.num_pages+1)

# 1.3、else 生成当前页码-5,到当前页码+6的列表
page_range=range(current_page_num-5,current_page_num+6)

# 2、其它情况,生成的列表就是pageinator的page_range
page_range=paginator.page_range     
5.3.1、视图
def index(request):
    # 需要的第三个参数
    page_num_int = int(request.GET.get('page', 1))
    book_list = models.Book.objects.all()
    paginator = Paginator(book_list, 1)

    # 需要的第一个参数: 页码的生成器 [1,2,3,4,5,6,7,8,9,10]
    # page_range = paginator.page_range
    if paginator.num_pages > 11:

        # 当前条件符合了以后,有三种情况
        if page_num_int - 5 < 1:
            page_range = range(1, 11)
        elif page_num_int + 5 > paginator.num_pages:
            page_range = range(paginator.num_pages - 10, paginator.num_pages + 1)
        else:
            page_range = range(page_num_int - 5, page_num_int + 5)
    else:
        page_range = paginator.page_range
    # 需要的第二个参数,获取某一页的page对象
    page = paginator.page(page_num_int)
    return render(request, 'index.html', {'page_range': page_range, 'page': page, 'page_num_int': page_num_int})
5.3.2、模板

与5.2.5模板一致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值