Django框架08
在django部分,如果你写代码的时候报错了
"""
1.pycharm窗口提示,前端console界面
2.仔细核对代码(单词写错写多)
3.浏览器缓存没有清除
4.端口号可能冲突了,一直跑的是之前的项目
5.重启你的计算机
(自己学会百度搜索问题,出现bug千万不要慌 要冷静分析 自己想出一个排查思路)
"""
-
图书管理系统图书的增删改查
"""
将之前所学的知识点尽量全部都用上
"""
-
choices参数
""" 在设计表的时候 针对可以列举完全的可能性字段 一般都是用choices参数 """ gender_choices = ((1,'male'),(2,'female'),(3,'others')) gender = models.IntegerField()
# 针对具有choices参数的字段 存储数据的时候还是按照字段本身的数据类型存储没有其他的约束,但是如果你存的字段在你列举的范围内 那么可以自动获取对应关系 user_obj.gender # 数字 user_obj.get_gender_display() # 固定格式 get_choices参数字段名_display() """有对应关系就拿对应关系,没有则还是数据本身不会报错"""
# 自己看看一些模型表的设计 体会choices参数的使用
-
MTV与MVC模型
"""
django自称是MTV框架,但是它的本质其实还是MVC
"""
-
多对多三种创建方式
# 全自动(本地测试用这个比较方便) authors = models.ManyToManyField(to="Author") # 自动创建第三张关系表 扩展性差 add,remove,clear,set
# 纯手动(基本不用) # 自己创建第三张表 自己建外键 # 扩展性高 但是无法利用orm简便的查询方法了
# 半自动(实际项目用这个,扩展性好) class Book(models.Model): authors = models.ManyToManyField(to="Author", through='Book2Author', through_fields=('book','author') ) class Author(models.Model): books = models.ManyToManyField(to="Author", through='Book2Author', through_fields=('author','book') ) class Book2Author(models.Model): book = 外键() author = 外键() """ 第三张关系表 还是需要你自己手动建 但是你可以告诉django orm可以使用orm简便查询方法 """ -
ajax
""" 异步提交 局部刷新 参考案例:github注册实时获取用户名发送给后端确认并动态展示校验结果(页面不刷新) 复习:input框实时监测事件 input事件 我们学的是jQuery版本的ajax,所以你必须要确保html页面已经提前加载了jQuery """ # ajax基本语法 $.ajax({ url:'', # 朝后端哪个地址发送 跟action三种书写方式一致 type:'get/post', # 提交方式 默认get 跟form表单method参数一致 data:{'username':'jason','password':123}, # 要发送的数据 success:function(args){ # 异步回调处理机制 } }) """ 当你在利用ajax进行前后端交互的时候 后端无论返回什么都只会被回调函数接受 而不再影响这个浏览器页面了 """ # 扩展 参数 代码发布项目还会涉及 dataType:'JSON' """ 当后端是以HttpResponse返回的json格式的数据 默认是不会自动反序列化的 1.自己手动JSON.parse() 2.配置dataType参数 """ # 结论:写ajax的时候 你可以直接将dataType参数加上 以防万一 或者后端就用JsonResonse $.ajax({ url:'', # 朝后端哪个地址发送 跟action三种书写方式一致 type:'get/post', # 提交方式 默认get 跟form表单method参数一致 dataType:'JSON', data:{'username':'jason','password':123}, # 要发送的数据 success:function(args){ # 异步回调处理机制 } })
今日内容概要
-
前后端传输数据的编码格式(contentType)
-
ajax发送json格式数据
-
ajax发送文件数据
-
ajax结合sweetalert实现删除按钮的二次确认
-
django自带的序列化组件(drf做铺垫)
-
批量插入
-
自己写一个分页器(只需要掌握分页器的推导思路即可)
-
自定义分页器的使用(简单几行代码即可 需要掌握)
-
forms组件
今日内容详细
前后端传输数据的编码格式(contentType)
# 我们主要研究post请求数据的编码格式 """ get请求数据就是直接放在url后面的 url?username=jason&password=123 """ # 可以朝后端发送post请求的方式 """ 1.form表单 2.ajax请求 """ """ 前后端传输数据的编码格式 urlencoded formdata json """
# 研究form表单 默认的数据编码格式是urlencoded 数据格式:username=jason&password=123 django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中 username=jason&password=123 >>> request.POST 如果你把编码格式改成formdata,那么针对普通的键值对还是解析到request.POST中而将文件解析到request.FILES中 form表单是没有办法发送json格式数据的
# 研究ajax 默认的编码格式也是urlencoded 数据格式:username=jason&age=20 django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中 username=jason&age=20 >>> request.POST
ajax发送json格式数据
""" 前后端传输数据的时候一定要确保编码格式跟数据真正的格式是一致的 不要骗人家!!! {"username":"jason","age":25} 在request.POST里面肯定找不到 django针对json格式的数据 不会做任何的处理 request对象方法补充 request.is_ajax() 判断当前请求是否是ajax请求 返回布尔值 """
<script> $('#d1').click(function () { $.ajax({ url:'', type:'post', data:JSON.stringify({'username':'jason','age':25}), contentType:'application/json', // 指定编码格式 success:function () { } }) }) </script> json_bytes = request.body json_str = json_bytes.decode('utf-8') json_dict = json.loads(json_str) # json.loads括号内如果传入了一个二进制格式的数据那么内部自动解码再反序列化 json_dict = json.loads(json_bytes)
""" ajax发送json格式数据需要注意点 1.contentType参数指定成:application/json 2.数据是真正的json格式数据 3.django后端不会帮你处理json格式数据需要你自己去request.body获取并处理 """
ajax发送文件
""" ajax发送文件需要借助于js内置对象FormData """
<script> // 点击按钮朝后端发送普通键值对和文件数据 $('#d4').on('click',function () { // 1 需要先利用FormData内置对象 let formDateObj = new FormData(); // 2 添加普通的键值对 formDateObj.append('username',$('#d1').val()); formDateObj.append('password',$('#d2').val()); // 3 添加文件对象 formDateObj.append('myfile',$('#d3')[0].files[0]) // 4 将对象基于ajax发送给后端 $.ajax({ url:'', type:'post', data:formDateObj, // 直接将对象放在data后面即可 // ajax发送文件必须要指定的两个参数 contentType:false, // 不需使用任何编码 django后端能够自动识别formdata对象 processData:false, // 告诉你的浏览器不要对你的数据进行任何处理 success:function (args) { } }) }) </script> def ab_file(request): if request.is_ajax(): if request.method == 'POST': print(request.POST) print(request.FILES) return render(request,'ab_file.html')
""" 总结: 1.需要利用内置对象FormData // 2 添加普通的键值对 formDateObj.append('username',$('#d1').val()); formDateObj.append('password',$('#d2').val()); // 3 添加文件对象 formDateObj.append('myfile',$('#d3')[0].files[0]) 2.需要指定两个关键性的参数 contentType:false, // 不需使用任何编码 django后端能够自动识别formdata对象 processData:false, // 告诉你的浏览器不要对你的数据进行任何处理 3.django后端能够直接识别到formdata对象并且能够将内部的普通键值自动解析并封装到request.POST中 文件数据自动解析并封装到request.FILES中 """
django自带的序列化组件(drf做铺垫)
""" 如果发现你可以直接使用MySQL但是无法使用sqlite3 不要慌张不要恐惧 你只需要按照之前MySQL的操作将sqlite3的驱动装一下即可 """
# 需求:在前端给我获取到后端用户表里面所有的数据 并且要是列表套字典 import json from django.http import JsonResponse from django.core import serializers def ab_ser(request): user_queryset = models.User.objects.all() # [{},{},{},{},{}] user_list = [] for user_obj in user_queryset: tmp = { 'pk':user_obj.pk, 'username':user_obj.username, 'age':user_obj.age, 'gender':user_obj.get_gender_display() } user_list.append(tmp) return JsonResponse(user_list,safe=False) return render(request,'ab_ser.html',locals())
# 序列化 res = serializers.serialize('json',user_queryset) """会自动帮你将数据变成json格式的字符串 并且内部非常的全面""" return HttpResponse(res) """ [ {"pk": 1, "username": "jason", "age": 25, "gender": "male"}, {"pk": 2, "username": "egon", "age": 31, "gender": "female"}, {"pk": 3, "username": "kevin", "age": 32, "gender": "others"}, {"pk": 4, "username": "tank", "age": 40, "gender": 4} ] 前后端分离的项目 作为后端开发的你只需要写代码将数据处理好 能够序列化返回给前端即可 再写一个接口文档 告诉前端每个字段代表的意思即可 [ { "model": "app01.user", "pk": 1, "fields": {"username": "jason", "age": 25, "gender": 1}}, { "model": "app01.user", "pk": 2, "fields": {"username": "egon", "age": 31, "gender": 2}}, { "model": "app01.user", "pk": 3, "fields": {"username": "kevin", "age": 32, "gender": 3}}, { "model": "app01.user", "pk": 4, "fields": {"username": "tank", "age": 40, "gender": 4}} ] 写接口就是利用序列化组件渲染数据然后写一个接口文档 该交代交代一下就完事 """
ajax结合sweetalert
""" 自己要学会如何拷贝 学会基于别人的基础之上做修改 研究各个参数表示的意思 然后找葫芦画瓢 """
<script> $('.del').on('click',function () { // 先将当前标签对象存储起来 let currentBtn = $(this); // 二次确认弹框 swal({ title: "你确定要删吗?", text: "你可要考虑清除哦,可能需要拎包跑路哦!", type: "warning", showCancelButton: true, confirmButtonClass: "btn-danger", confirmButtonText: "是的,老子就要删!", cancelButtonText: "算了,算了!", closeOnConfirm: false, closeOnCancel: false, showLoaderOnConfirm: true }, function(isConfirm) { if (isConfirm) { // 朝后端发送ajax请求删除数据之后 再弹下面的提示框 $.ajax({ {#url:'/delete/user/' + currentBtn.attr('delete_id'), // 1 传递主键值方式1#} url:'/delete/user/', // 2 放在请求体里面 type:'post', data:{'delete_id':currentBtn.attr('delete_id')}, success:function (args) { // args = {'code':'','msg':''} // 判断响应状态码 然后做不同的处理 if(args.code === 1000){ swal("删了!", args.msg, "success"); // 1.lowb版本 直接刷新当前页面 {#window.location.reload()#} // 2.利用DOM操作 动态刷新 currentBtn.parent().parent().remove() }else{ swal('完了','出现了位置的错误','info') } } }) } else { swal("怂逼", "不要说我认识你", "error"); } }); }) </script>
批量插入
def ab_pl(request): # 先给Book插入一万条数据 for i in range(10000): models.Book.objects.create(title='第%s本书'%i) # 再将所有的数据查询并展示到前端页面 book_queryset = models.Book.objects.all() # 批量插入 book_list = [] for i in range(100000): book_obj = models.Book(title='第%s本书'%i) book_list.append(book_obj) models.Book.objects.bulk_create(book_list) """ 当你想要批量插入数据的时候 使用orm给你提供的bulk_create能够大大的减少操作时间 :param request: :return: """ return render(request,'ab_pl.html',locals())
分页器
""" 总数据100 每页展示10 需要10 总数据101 每页展示10 需要11 总数据99 每页展示10 需要10 如何通过代码动态的计算出到底需要多少页? 在制作页码个数的时候 一般情况下都是奇数个 符合中国人对称美的标准 """
# 分页 book_list = models.Book.objects.all() # 想访问哪一页 current_page = request.GET.get('page',1) # 如果获取不到当前页码 就展示第一页 # 数据类型转换 try: current_page = int(current_page) except Exception: current_page = 1 # 每页展示多少条 per_page_num = 10 # 起始位置 start_page = (current_page - 1) * per_page_num # 终止位置 end_page = current_page * per_page_num # 计算出到底需要多少页 all_count = book_list.count() page_count, more = divmod(all_count, per_page_num) if more: page_count += 1 page_html = '' xxx = current_page if current_page < 6: current_page = 6 for i in range(current_page-5,current_page+6): if xxx == i: page_html += '<li class="active"><a href="?page=%s">%s</a></li>'%(i,i) else: page_html += '<li><a href="?page=%s">%s</a></li>'%(i,i) book_queryset = book_list[start_page:end_page]
""" django中有自带的分页器模块 但是书写起来很麻烦并且功能太简单 所以我们自己想法和设法的写自定义分页器 上述推导代码你无需掌握 只需要知道内部逻辑即可 我们基于上述的思路 已经封装好了我们自己的自定义分页器 之后需要使用直接拷贝即可 """