Django框架第九篇--Django和Ajax、序列化组件(serializers)、自定义分页器、模型表choice参数
Django和Ajax
一、什么是Ajax
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
二、Ajax的优点
优点:
- AJAX使用JavaScript技术向服务器发送异步请求;
- AJAX请求无须刷新整个页面;
- 因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高;
- 两个关键点:1.局部刷新,2.异步请求

三、基于jQuery实现的Ajax
1.基本语法
// 在html script中使用
$.ajax({
url:'/index/', //提交数据路径,不写默认是当前路径
type:'post', //标定ajax的请求方式
data:{'name':'lqz','age':18}, //data后面跟的就是你提交给后端的数据
//success为回调函数
success:function (data) { //data即后端给你返回的数据
alert(data)
}
})
2.利用ajax提交表单中的数据 (数字的相加例子)
index.html
<!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> </head>
<body>
<input type="text" id="i1">+<input type="text" id="i2">=<input type="text" id="i3">
<button class="btn btn-primary" id="d1" >求和</button> <script>
//绑定点击事件
$('#d1').click(function () {
//ajax写法
$.ajax({
url:'/index/' ,
type:'post', //设置发送方式是post请求
//获取两个输入框的值
data:{'i1':$('#i1').val(),'i2':$('#i2').val()}, //data是提交给后端的数据
//success回调函数
success:function (data) { //data是后端返回的数据
$('#i3').val(data)
}
})
})
</script>
</body>
</html>
views.py
def index(request):
# print(request.is_ajax()) # 用来判断当前请求方式是否是ajax请求
if request.is_ajax():
if request.method == 'POST':
# print(request.POST)
#i1和i2是ajax传递过来的data字典键
i1 = request.POST.get('i1')
i2 = request.POST.get('i2')
# 后端获取的前端数据 都是字符串格式
res = int(i1) + int(i2)
return HttpResponse(res) #返回给ajax return render(request,'index.html')
需要注意的
1.在设置ajax的url路径的时候,不写就是朝当前地址提交数据,如果你写了要注意路径格式,比如是这样('/index/')
2.type是设置ajax的请求方式,如果你写的是post,views视图就是通过request.POST.get获取数据,如果type是get请求方式,就是通过request.GET.get获取数据。type值为空时,默认是get方法
四、form表单和ajax进行文件上传
1.contentType前后端传输数据编码格式
前后端传输数据编码格式
- urlencoded
- formdata
- json
2.form表单和ajax上传文件区别
form表单
1.默认使用的编码格式是urlencoded
数据格式:name = jason&pwd=123
django后端针对urlencoded编码格式的数据会自动解析并放在request.POST中供用户获取。 2.可以修改formdata传文件
django后端针对formdata编码格式的数据会自动解析并放在request.FILES中供用户获取。
注意:前后端传输数据的时候一定要保证数据格式和你的编码格式是一致的
模板层
<!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> </head>
<body>
<form action="" enctype="multipart/form-data" method="post">
<input type="text" name="name" id="name">
<input type="file" name="myfile" id="myfile">
<input type='submit' value = 'form表单上传文件'> //form表单上传文件格式
</form>
<button id="btn">ajax提交文件</button> //ajax上传文件格式,触发下面的ajax <script>
//绑定提交按钮
$('#btn').click(function () {
//上传文件,建议使用Formdata
var formdata =new FormData(); //既可以传普通键值对,也可以传文件
//添加普通键值对
formdata.append('name',$('#name').val());
//传文件,$('#myfile')[0].files拿到的是文件列表,取第0个把具体文件拿出来
formdata.append('myfile',$('#myfile')[0].files[0]);
$.ajax({
url:'',
type:'post',
data:formdata,
processData:false, //告诉前端不要处理数据
contentType:false, //不适用任何编码,因为formdata对象自带编码,django后端也能够识别formdata对象 success:function (data) { //后端返回给前端信息
alter(data)
}
})
})
</script>
</body>
</html>
视图层
#forms表单上传文件
def home(request):
if request.method == 'GET': //渲染页面
return render(request,'home.html')
#获取文件信息
myfile = request.FILES.get('myfile') //获取form表单上传的文件
print(myfile) //上传文件名
return HttpResponse('ok') #ajax上传文件
def home_ajax(request):
if request.is_ajax():
if request.method == 'POST':
name = request.POST.get('name')
print(name) #input框内容
myfile = request.FILES.get('myfile')
print(myfile) #文件名
print(myfile.name) #文件名
return HttpResponse('ok') return render(request,'home.html')
路由层
url(r'^home/',views.home,name='home'), //form表单上传文件
url(r'^home_ajax/',views.home_ajax,name='home_ajax'), //ajax上传文件
注意点
1.form表单上传文件需要指定编码格式enctype = 'multipart/form-data'。ajax也需要设置一样的编码格式,然后需要创建一个Formdata对象
获取file文件的内容都是通过request.FILES.get()
2.通过append的方法,给对象传值,相当于设置了一个个的键值对。
3.必须要设置这两个参数
processData:false
contentType:false
五、基于ajax提交json格式数据
1.ajax提交数据
ajax默认数据提交方式也是urlencoded ajax发送json格式数据
django后端针对json格式的数据 并不会自动解析放到request.POST或者request.FILES里面
它并不会解析json格式数据 而是将它原封不动的放在request.body中了
模板层
<!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> </head>
<body>
<input type="text" name="name" id="d1">
<input type="password" name="password" id="d2">
<button id="d3">ajax提交json格式数据</button>
</body>
<script>
$('#d3').click(function () {
var pos_data = {'name':$('#d1').val(),'password':$('#d2').val()}; //获取input框数据
//JSON.stringify相当于json.dumps(),转化成json格式的字符串
var pos = JSON.stringify(pos_data); //转换格式 $.ajax({
url:'',
type:'post',
data:pos, //发送的数据
contentType:'application/json', //告诉后端你这次的数据是json格式
dataType:'json',
success:function (data) {
alert(data)
} })
})
</script>
</html>
视图层
#ajax提交json数据
def home_json(request):
if request.method == 'POST':
#后端 需要手动去request.body中获取json格式数据
print(request.body)
import json
bytes_str = request.body.decode('utf-8')
print(json.loads(bytes_str))
return HttpResponse('ok') return render(request,'home_json.html')
路由层
url(r'^home_json/',views.home_json,name='home_json'),
总结:
1.如果不是上传文件,form表单input的话,就直接传了,contentType默认是urlencoded编码方式
2.如果是上传文件,ajax上传文件就是先创建一个Formdata对象,通过append,把key,value参数传进去。注意:form表单和ajax上传的文件都是通过request.FILES.get()获取。
3.ajax提交json格式的数据,先创造出一个对象,把数据放在对象里面,然后转换成json格式的字符串,通过JSON.stringify(data),这里的contentType必须设置为'application/json',这样它的数据在视图中就能通过request.body获取到,是二进制格式,需要转换成字符串。
4、在前端接收到后台json格式数据,可以在ajax那里写dataType:'json',它会自动转换成对象
六、序列化组件
from django.core import serializers # django自带的一个小型的序列化工具
def reg(request):
user_list = models.User.objects.all()
res = serializers.serialize('json',user_list)
return render(request,'index.html',locals())
[{
"model": "app01.user",
"pk": 1,
"fields": {
"username": "jason",
"age": 18,
"gender": 1
}
}, {
"model": "app01.user",
"pk": 2,
"fields": {
"username": "tank",
"age": 24,
"gender": 3
}
}, {
"model": "app01.user",
"pk": 3,
"fields": {
"username": "egon",
"age": 73,
"gender": 2
}
}, {
"model": "app01.user",
"pk": 7,
"fields": {
"username": "kevin",
"age": 29,
"gender": 4
}
}]
七、自定义分页器
批量插入数据 bulk_create()
for i in range(1000):
models.Book.objects.create(title='第%s本书'%i)
上面这种方式 效率极低 l = []
for i in range(10000):
l.append(models.Book(title='第%s本书'%i))
models.Book.objects.bulk_create(l) # 批量插入数据
自定义分页器的使用
拷贝下面分页器代码,放在某个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)
分页器代码
后端代码
from app01.utils.mypage import Pagination //导入分页器代码
book_list = models.Book.objects.all() //查询所有数据
current_page = request.GET.get("page",1)
all_count = book_list.count() //总条数
page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10)
page_queryset = book_list[page_obj.start:page_obj.end] return render(request,'booklist.html',locals())
前端代码
{% for book in page_queryset %}
<p>{{ book.title }}</p>
{% endfor %}
{{ page_obj.page_html|safe }}
八、模型表参数choice
比如选择性别男女,往数据库中填写的是数字1,2
模型层
class User(models.Model):
username = models.CharField(max_length=32)
age = models.IntegerField()
choices = (
(1,'男'),(2,'女'),(3,'其他')
)
gender = models.IntegerField(choices=choices)
视图层
user_obj = models.User.objects.filter(pk=1).first() print(user_obj.get_gender_display()) #男
"""
只要是choices字段 在获取数字对应的注释 固定语法
get_choices字段名_display()
"""
注意:
1 存choice里面罗列的数字与中文对应关系
print(user_obj.get_gender_display())
只要是choices字段 通过数字获取对应的汉字
固定语法
get_choices字段名_display() 2 存没有罗列出来的数字
不会报错 还是展示数字
Django框架第九篇--Django和Ajax、序列化组件(serializers)、自定义分页器、模型表choice参数的更多相关文章
- Django框架深入了解_02(DRF之序列化、反序列化)
序列化:将Python对象准换成json格式的字符串,反之即为反序列化 DRF的序列化使用过程: 使用drf的序列化组件 -1 新建一个序列化类继承Serializer -2 在类中写要序列化的字段 ...
- Django框架第一篇基础
一个小问题: 什么是根目录:就是没有路径,只有域名..url(r'^$') 补充一张关于wsgiref模块的图片 一.MTV模型 Django的MTV分别代表: Model(模型):和数据库相关的,负 ...
- Django基础-04篇 Django开发前后端联动
1. 写views views.py代码块 1.在前端以/article/{{ article.id }}这种方式请求后台, 参数配置在urls.py中path('category/<int:i ...
- Django序列化组件Serializers详解
本文主要系统性的讲解django rest framwork 序列化组件的使用,基本看完可以解决工作中序列化90%的问题,写作参考官方文档https://www.django-rest-framewo ...
- Django框架(十二)—— 补充:inclusion_tag、defer、only、choice、事务、创建多对多的第三张表
目录 补充:inclusion_tag.defer.only.choice.事务.创建多对多的第三张表 一.inclusion_tag 1.作用 2.使用 二.defer与only 1.定义 2.使用 ...
- 潭州课堂25班:Ph201805201 django框架 第九课 模型补充 博客小案例 (课堂笔记)
聚合查询: 分组查询: annotate() 方法 例:查询某学院学生人数,(一对多查询) 以字典的形式输出 annotate(统计 ‘关联学生字段 出现的次,).字典形式(键,值) 例:查询每项课程 ...
- django框架--登录注册功能(ajax)
注册 实现一个注册功能 编写 html 内容 input 标签 csrf_token ajax 路由 视图: 提供页面 负责处理业务,返回响应 接收到 post 请求传递的参数 写库 返回 ...
- Django框架深入了解_03(DRF之认证组件、权限组件、频率组件、token)
一.认证组件 使用方法: ①写一个认证类,新建文件:my_examine.py # 导入需要继承的基类BaseAuthentication from rest_framework.authentica ...
- 第六章、ajax方法以及序列化组件
目录 第六章.ajax方法 一.choice参数介绍 二.MTV与MVC模型 三.ajax方法 四.案例 五.Ajax传json格式的数据 六. AJAX传文件 代码如下 ajax传文件需要注意的事项 ...
随机推荐
- pipelinewise 学习一 docker方式安装
pipelinewise 没有提供基于pip 包的模式进行安装,而且推荐使用docker 以及源码的方式 以下是一个使用docker运行的方式 安装 git clone https://githu ...
- ESA2GJK1DH1K微信小程序篇: 安装Nginx,配置反向代理
前言 一,为什么需要反向代理 小程序访问的是 443端口,咱需要把443端口的数据传给MQTT 这节为了避免大家配置出错,以下源码已经配置. 如果大家想自己配置,请参考 https://www.cnb ...
- [CQOI2007]涂色paint(BZOJ 1260)题解
题目描述 假设你有一条长度为5的木版,初始时没有涂过任何颜色.你希望把它的5个单位长度分别涂上红.绿.蓝.绿.红色,用一个长度为5的字符串表示这个目标:RGBGR. 每次你可以把一段连续的木版涂成一个 ...
- ImportError: cannot import name 'DjangoSuitConfig'
pip3.6 install https://github.com/darklow/django-suit/tarball/v2
- Vector与ArrayList 的理解
最近在看Vector与ArrayList的源码,看下他们的区别与联系. Vector是线程安全的集合类,ArrayList并不是线程安全的类.Vector类对集合的元素操作时都加了synchroniz ...
- OO助教的退休感想
深夜失眠+刚赶完火车的胡言乱语,切莫当真,择日修改 一年前,我在学姐的怂恿鼓励下,加上了吴老师的微信,表达了想担任下学期的OO助教的想法.三天后,我到新主楼参加OO助教的面试,其实还是蛮紧张的,毕竟自 ...
- JCR分区 | 中科院SCI期刊分区表
LetPub查询系统,非常方便,分区影响因子都可以查询,还有投稿经验可以参考. SCI全称是Science Citation Index(科学引文索引) 科睿唯安JCR分区(Journal Citat ...
- pygis库组件安装相关问题
python -m pip install --upgrade pip
- Centos7 搭建wordpress
WordPress是使用PHP语言开发的博客平台,用户可以在支持PHP和MySQL数据库的服务器上架设属于自己的网站.也可以把 WordPress当作一个内容管理系统(CMS)来使用. 搭建WordP ...
- sublime px转rem的方法【亲测有效】
在开发手机网站的时候,我们经常会用到rem来作为单位,但是手动转rem太麻烦了,那么怎么办呢?sublime安装cssrem来进行快捷操作. 安装过程: 第一步:去git上克隆 https://git ...