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参数的更多相关文章

  1. Django框架深入了解_02(DRF之序列化、反序列化)

    序列化:将Python对象准换成json格式的字符串,反之即为反序列化 DRF的序列化使用过程: 使用drf的序列化组件 -1 新建一个序列化类继承Serializer -2 在类中写要序列化的字段 ...

  2. Django框架第一篇基础

    一个小问题: 什么是根目录:就是没有路径,只有域名..url(r'^$') 补充一张关于wsgiref模块的图片 一.MTV模型 Django的MTV分别代表: Model(模型):和数据库相关的,负 ...

  3. Django基础-04篇 Django开发前后端联动

    1. 写views views.py代码块 1.在前端以/article/{{ article.id }}这种方式请求后台, 参数配置在urls.py中path('category/<int:i ...

  4. Django序列化组件Serializers详解

    本文主要系统性的讲解django rest framwork 序列化组件的使用,基本看完可以解决工作中序列化90%的问题,写作参考官方文档https://www.django-rest-framewo ...

  5. Django框架(十二)—— 补充:inclusion_tag、defer、only、choice、事务、创建多对多的第三张表

    目录 补充:inclusion_tag.defer.only.choice.事务.创建多对多的第三张表 一.inclusion_tag 1.作用 2.使用 二.defer与only 1.定义 2.使用 ...

  6. 潭州课堂25班:Ph201805201 django框架 第九课 模型补充 博客小案例 (课堂笔记)

    聚合查询: 分组查询: annotate() 方法 例:查询某学院学生人数,(一对多查询) 以字典的形式输出 annotate(统计 ‘关联学生字段 出现的次,).字典形式(键,值) 例:查询每项课程 ...

  7. django框架--登录注册功能(ajax)

    注册 实现一个注册功能 编写 html 内容 input 标签 csrf_token ajax 路由 视图: 提供页面 负责处理业务,返回响应 接收到   post   请求传递的参数 写库 返回   ...

  8. Django框架深入了解_03(DRF之认证组件、权限组件、频率组件、token)

    一.认证组件 使用方法: ①写一个认证类,新建文件:my_examine.py # 导入需要继承的基类BaseAuthentication from rest_framework.authentica ...

  9. 第六章、ajax方法以及序列化组件

    目录 第六章.ajax方法 一.choice参数介绍 二.MTV与MVC模型 三.ajax方法 四.案例 五.Ajax传json格式的数据 六. AJAX传文件 代码如下 ajax传文件需要注意的事项 ...

随机推荐

  1. 洛谷p2370yyy2015c01的U盘题解

    没什么特殊的想法 就是看自己很久没有更新关于题解类的文章了而已 (其实这是我好久之前做的, 只是把它从洛谷博客搬到了这里而已) 题目 首先分析题目要二分 他长成这个亚子太二分了 所以就要二分 最好是先 ...

  2. CCF 201709-3 JSON查询

    CCF 201709-3 JSON查询 试题编号: 201709-3 试题名称: JSON查询 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 JSON (JavaScript ...

  3. C++中list的用法总结

    list简介 list 也是顺序容器的一种.只是list 是一个双向链表.使用 list 需要包含头文件 list.双向链表的每个元素中都有一个指针指向后一个元素,也有一个指针指向前一个元素,如下图所 ...

  4. centos服务器升级nodejs, pm2

    突然抽风想升级服务器的nodejs版本,原服务器版本运行的8.x,而目前(2019年5月30日)nodejs官方最新版本已经更新到了12.x了,稳定版本也更新到了10.x. 然后就折腾了一把去升级服务 ...

  5. uni-app 实现分享生成图片

    <template> <view> <view class="personal_li" @click="shareClick"&g ...

  6. ex2

    #include <stdio.h> int main() { int days; printf("输入一个整数: \n"); scanf("%d" ...

  7. 冰多多团队-第九次Scrum例会

    冰多多团队-第九次Scrum会议 工作情况 团队成员 已完成任务 待完成任务 zpj debug, IAT debug, IAT 牛雅哲 debug, IAT 接通新的语音识别接口和termux,完成 ...

  8. Python导入 from lxml import etree 导入不了

    问题在学爬虫,Python 版本是2.7,安装的lxml包是4.3的,在 from lxml import etree 时发现一直报错,网上查询,原来是Python版本和lxml包版本不一致导致的. ...

  9. [转]vscodesvn安装和使用

    原文链接:https://blog.csdn.net/wzh66888/article/details/90145340 1.安装svn插件 2.安装成功后会出现这样的图标 如果没有安装之后不能使用, ...

  10. 执行redis命令redis-trib.rb查看集群信息报错cannot load such file -- redis (LoadError)

    问题描述: 在执行redis-trib.rb命令查看集群状态的时候,报错: [aiprd@hadoop1 ~]$ redis-trib.rb check Traceback (most recent ...