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">«</span>
</a>
</li>
{% else %}
<li class="disabled">
<a href="" aria-label="Previous">
<span aria-hidden="true">«</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">»</span>
</a>
</li>
{% else %}
<li class="disabled">
<a href="" aria-label="Next">
<span aria-hidden="true">»</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})