Ajax
Ajax
(1)简介
-
Ajax(Asynchronous JavaScript and XML)翻译成中文就是
异步的Javascript和XML
。 -
Ajax最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
-
AJAX不需要任何浏览器插件,但需要用户允许Javascript在浏览器上执行。
-
异步提交 局部刷新
- 动态获取用户名实时的跟后端确认并实时展示的前端(局部刷新)
(2)案例
页面上有三个input框
在前两个框中输入数字 点击按钮 朝后端发送Ajax请求
后端计算出结果 再返回给前端动态展示到第三个input框中
(整个页面没有刷新,也不能在前端计算)
def testajax(request): if request.method == "POST": print(request.POST) # <QueryDict: {'username': ['heart'], 'age': ['18']}> num1 = request.POST.get('number1') num2 = request.POST.get('number2') res = int(num1) + int(num2) return HttpResponse(res) return render(request, 'testajax.html')
<body> <input type="text" id="input1"> + <input type="text" id="input2"> = <input type="text" id="input3"> <p> <button id="btn">点我</button> </p> </body> </html> <script> // 先给按钮绑定一个点击事件 $('#btn').click(function () { // 朝后端发送ajax请求 $.ajax({ url: '', // 不写就是朝当前页面发送请求 type: 'post', // 请求方式 data : {'number1':$('#input1').val(),'number2':$('#input2').val()}, // 发送的数据 // 回调函数: 当后端给你返回结果的时候会自动触发,args接受后端的返回结果 success: function(args){ $('#input3').val(args) } }) }) </script>
[1]如果从后端传的是个字典
- HttpResponse
def add_number(request): if request.method == "POST": data = request.POST result = { "message": "success", "result": result } return HttpResponse(json.dumps(result)) return render(request, "index.html")
<script> $(document).ready( $("#btn_result").click(function () { let numberOne = $("#numberOne").val(); let numberTwo = $("#numberTwo").val(); let result = $("#numberResult") $.ajax( { url: "", type: "post", data: {numberOne: numberOne, numberTwo: numberTwo}, // 前端反序列化数据 方式一 // 在Ajax上加参数 // dataType 参数应该是一个字符串,表示期望从服务器返回的数据类型(如 "json", "xml", "script", "html" 等) dataType: "json", success: function (data) { // 注意:data 表示返回的数据。 console.log(data) // {message: 'success', result: 4} result.val(data) // 表示将返回的数据赋值给 id 为 result 的元素的 value 属性。 } } ) }) ) </script>
- JsonResponse
def testajax(request): if request.method == "POST": dict = {'code':200,"msg":'ok'} return JsonResponse(dict) return render(request, 'testajax.html')
<body> <input type="text" id="input1"> + <input type="text" id="input2"> = <input type="text" id="input3"> <p> <button id="btn">点我</button> </p> </body> </html> <script> // 先给按钮绑定一个点击事件 $('#btn').click(function () { // 朝后端发送ajax请求 $.ajax({ url: '', // 不写就是朝当前页面发送请求 type: 'post', // 请求方式 // dataType: "json", data : {'number1':$('#input1').val(),'number2':$('#input2').val()}, // 发送的数据 // 回调函数: 当后端给你返回结果的时候会自动触发,args接受后端的返回结果 success: function(args){ console.log(typeof args) // 这样是object对象 $('#input3').val(args.code) } }) }) </script>
总结
针对后端如果是用HttpResponse返回的数据 回调函数不会自动反序列化
如果后端直接用的是JsonResponse返回的数据 回调函数会自动反序列化
HttpResponse解决方法
1.在前端利用JSON.parse()
2.在ajax里面配置一个参数dataType:true
(3)前后端传输数据编码格式
- urlencoded
- formdata
- json
[1]form表单
-
默认的数据编码格式是urlencoded
-
数据格式:username=heart&password=123
-
django后端针对符号urlencoded编码格式的数据都会自动解析封装到request.POST中
-
如果编码格式改成formdata,普通的键值对还是解析到request.POST中,而将文件解析到request.FILES中
-
form表单是没有办法发送json格式数据的
[2]ajax
- 默认的数据编码格式是urlencoded
(1)ajax发送json格式数据
- django针对json格式的数据,不会做任何的处理
data:JSON.stringify({'username':'heart','age':18}) contentType:'application/json', // 指定编码格式
request.is_ajax() #返回布尔值 if request.is_ajax(): print(request.body) # b'{"name":"heart","age":18}' # 针对json格式数据需要手动处理 json_bytes = request.body json_str = json_bytes.decode('utf-8') json_dict = json.loads(json_str) print(json_dict) # {'name': 'heart', 'age': 18}
# 其实json.loads括号内如果传入了一个二进制格式的数据那么内部可以自动解码再反序列化 json_bytes = request.body json_sict = json.loads(json_bytes)
总结
1.contentType参数指定成:application/json
2.数据是真正的json格式数据
3.django后端不会处理json格式数据需要自己在request.body获取并处理
(2)ajax发送文件
- ajax发送文件需要借助于js内置对象FormData
var formData = new FormData(); formData.append('username', $('#d1').val()); contentType: false processData: false
def fileajax(requst): if requst.is_ajax(): if requst.method =='POST': print(requst.POST) print(requst.FILES) # <QueryDict: {'username': ['123'], 'password': ['123']}> # <MultiValueDict: {'file': [<TemporaryUploadedFile: 【3.0】Django框架.pdf (application/pdf)>]}> return render(requst,'fileajax.html')
<body> <p>username: <input type="text" id='d1'></p> <p>password: <input type="password" id='d2'></p> <p><input type="file" id="d3"></p> <button class="btn btn-success" id="d4">点我</button> </body> <script> $('#d4').click(function () { // 需要先利用FormData内置对象 var formData = new FormData(); // 添加普通的键值对 formData.append('username', $('#d1').val()); formData.append('password', $('#d2').val()); // 添加文件 formData.append('file', $('#d3')[0].files[0]); // 将对象基于ajax发送给后端 $.ajax({ url: '', type: 'post', data: formData, contentType: false, // 不需要使用任何编码 django后端能够自动识别formdata对象 processData: false, // 不需要将data转换为字符串 success: function (data) { console.log(data) } }) }) </script>
(4)django自带的序列化组件
from django.core import serializers
user_queryset = models.User.objects.all() res = serializers.serialize('json',user_queryset) # 会自动将数据变成json格式的字符串 并且内部非常全面 return HttpResponse(res)
(5)批量插入数据
- 当想要批量插入数据的时候,使用orm提供的bulk_create能够大大的减少操作时间
def plcr(request): book_list = [] for i in range(10000): book_obj = models.Book(title=f'第{i}本书') book_list.append(book_obj) models.Book.objects.bulk_create(book_list) return render(request,'plcr.html',locals())
(6)自定义分页器
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: 最多显示的页码个数 """ 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)
(1)使用示例
- 后端
def get_book(request): 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())
- 前端
<div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> {% for book in page_queryset %} <p>{{ book.title }}</p> {% endfor %} {{ page_obj.page_html|safe }} </div> </div> </div>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通