Django查询
聚合查询 关键字:aggregate from django.db.models import Max,Min,Count,Sum,Avg 分组查询 关键字:annotate 1.最简单的规律 models后面点什么 就是按什么分组 F与Q查询 from django.db.modles import F,Q F 能够帮助你获取到表中字段所对应的数据 # 书籍的库存数与卖出数 models.Book.objects.filter(kucun__gt=F('maichu')) 因为filter过滤的条件的都是and连接 modesls.Book.objects.filter(Q(title='python'),Q(price=666)) modesls.Book.objects.filter(Q(title='python')|Q(price=666)) modesls.Book.objects.filter(~Q(title='python')|Q(price=666)) # Q进阶用法 q = Q() q.connector = 'or' q.children.append(('title','python')) q.children.append(('title__icontains','python')) q.children.append(('price',666)) models.Book.objects.filter(q) # 默认还是and关系 django中如何开启事务 from django.db import transaction try: with transaction.atomic(): # 事务操作 except BaseException as e: print(e) 常见字段及参数 AutoField() DateField() DateTimeField() auto_now auto_now_add TextField() EmailField() varchar(...) BooleanField() 传布尔值 存0/1 自定义char字段 class MyCharField(models.Field): def db_type(self,connection): return 'char(%s)'%self.max_length orm查询优化 only defer select_related prefetch_related 图书管理系统 书籍的增删改查
模型表的choice参数
比如选择性别‘男女’,往数据库中填写的数字是0,1
模型层
class Userinfo(models.Model): username = models.CharField(max_length=32) password = models.IntegerField() # 定义 choice 参数 choices = ( (1, 'male'), (2, 'female'), (3, 'others') ) gender = models.IntegerField(choices=choices) ''' 定义choice参数时,括号内放的对应关系是一个个元组,如果我存入的数字不在我模型层 定义的choice参数内(注意:虽然存入的数字没有对应关系,但是是可以存的) '''
视图层
from app01 import models res = models.Userinfo.objects.filter(pk=1).first() ret = models.Userinfo.objects.filter(pk=4).first() print(res.username) #jason print(res.gender) # 1 # 正确方式 print(res.get_gender_display()) # male print(ret.username) # nick print(ret.gender)# 3 # 正确方式 print(ret.get_gender_display()) # others res = models.Userinfo.objects.filter(pk=5).first() print(res.get_gender_display()) # 4 数字4没有在choice参数内设置对应值,所以取出的 任然是数字 ''' 如上所示,针对choices字段,如果你想要获取数字对应的值,不能直接点字段取值 固定的书写方式为:数据对象.get_字段名_display(),当需要取值的数字不在choice参数内所设置的对应关系,那么取值获取到的还是数字 '''
choice参数使用模版
record_choices = (('checked', "已签到"), ('vacate', "请假"), ('late', "迟到"), ('noshow', "缺勤"), ('leave_early', "早退"), ) record = models.CharField("上课纪录", choices=record_choices, default="checked",) score_choices = ((100, 'A+'), (90, 'A'), (85, 'B+'), (80, 'B'), (70, 'B-'), (60, 'C+'), (50, 'C'), (40, 'C-'), (0, ' D'), (-1, 'N/A'), (-100, 'COPY'), (-1000, 'FAIL'), ) score = models.IntegerField("本节成绩", choices=score_choices, default=-1)
MTV与MVC模型
django号称是MTV框架,其实它还是MVC框架 MTV: M: models T: templates V: views MVC: M: modles V: views C: controller(路由匹配)
Ajax(*****)
什么是Ajax: AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;(等待期间不做任何事)
异步交互:客户度发出一个请求后,不需要等待服务器响应结束,可直接发出第二个请求。(直接执行下一行代码)
阻塞与非阻塞:表示的是程序的执行状态
Ajax优点
- AJAX使用JavaScript技术向服务器发送异步请求;
- AJAX请求无须刷新整个页面;
- 因为服务器响应内容不再是整个页面,而是页面中的部分内容,所以AJAX性能高;
两个关键点:1.局部刷新:一个页面,不是整体刷新,而是页面的某个地方局部刷新
2.异步提交
基于jQuery实现的Ajax
ajax基本语法
//在 html script中使用 $.ajax({ url: '/index/', //提交的数据路径,不写默认是当前路径 type: 'post', //标定ajax的请求方式 data:{'name':'jason', 'age': 18}, //data后面跟的是你提交给后端的数据 //success 为回调函数 success:function(data){ //data是后端返回的数据 alert(data) } })
1.展示一个前端页面,页面上有三个输入框,前面两个框输入数字,点击按钮朝后端发送请求,页面在不刷新的情况下,完成数字的加法运算
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> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script> </head> <body> <input type="text" id="t1">+<input type="text" id="t2">=<input type="text" id="t3"> <p> <button class='btn btn-primary' id="b1">计算</button> </p> <script> //绑定事件 $('#b1').on('click',function(){ //ajax写法 $.ajax({ url: '/index/', type: 'post', //设置发送方式是post请求 //获取两个输入框的值 data:{'t1':$('#t1').val(), 't2':$('#t2').val()},//data是提交给后端的数据 //success回调函数 success:function(data){ //data是后端返回的数据 $('#t3').val(data) } }) }) </script> </body> </html>
views.py
def index(request): if request.is_ajax(): if request.method == 'POST': t1 = request.POST.get('t1') # 后端获取到前端的数据都是字符串形式 t2 = request.POST.get('t2') # 后端获取到前端的数据都是字符串形式 res = int(t1) + int(t2) # 转换成 int类型 return HttpResponse(res) return render(request, 'index.html')
Ajax传 json 格式数据
django后端针对json格式的数据,不会自动帮你解析,会原封不动的存放在 request.body 中,
可以手动处理,获取数据
json_bytes = request.body json.str = str(json_bytes,encoding='utf8') json_dict = json.loads(json.str) 注意点:在前端html 中必须: 1.指定contentType参数 contentType: 'application/json' 2.要将你发送的数据,确保是json格式的 data:JSON.stringify({'username': 'jason', 'password': '123'})
js.html.py
<!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>
视图层
def js(request): if request.method == 'POST': json_bytes = request.body # 后端 需要手动去request.body中获取json格式数据 print(request.body) # b'{"name":"tank","password":"123"}' import json bytes_str = request.body.decode('utf-8') print(json.loads(bytes_str)) # {'name': 'tank', 'password': '123'} return render(request, 'js.html')
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中供用户获取。
需要利用内置对象 Formdata,该对象即可以传普通键值,也可以传文件
模型层
<!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="username" id="t1"> <input type="password" name="password" id="t2"> <input type="file" name="myfile" id="myfile"> <input type='submit' value = 'form表单上传文件'> //form表单上传文件格式 </form> <button id="b1">提交</button> //ajax上传文件格式,触发下面的ajax <script> //绑定提交按钮 $('#b1').click(function() { //1.先生成一个Formdata对象 var myFormdata = new FormData(); //2.朝对象中添加普通键值 myFormdata.append('username', $('#ti').val()); //既可以上传普通键值 myFormdata.append('password', $('#t2').val()); //3.朝对象中添加文件数据,分三步 //1.先通过jQuery获取查到到标签 //2.将jQuery对象转换成原生的js 对象 //3.利用原生js对象的方法,直接获取文件内容 myFormdata.append('myfile', $('#t3')[0].files[0]); //也可以上传文件 $.ajax({ url: '', type: 'post', data:myFormdata, //直接丢对象 // ajax传文件,一定要指定两个关键性的参数 contentType: false, //不用任何编码,因为Formdata对象自带编码,django能够识别该对象 processData: false, //告诉浏览器不要处理我的数据,直接发就行 success:function(data){ //后端返回给客户端数据 alert(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 upload(request): if request.is_ajax: if request.method == 'POST': print(request.POST) # <QueryDict: {'username': ['undefined'], 'password': ['111']}> print(request.FILES) # <MultiValueDict: {'myfile': [<InMemoryUploadedFile: 考试内容.txt (text/plain)>]}> return HttpResponse('后端已收到') return render(request, 'upload.html')
'''注意事项:ajax传文件需要注意的事项 1.利用formdata对象,能够简单的快速传输数据(普通键值 + 文件) 2.有几个参数 data:formdata 直接丢对象 contentType: false processData: false ''' '''1.form表单上传文件需要指定编码格式enctype = 'multipart/form-data'。ajax也需要设置一样的编码格式,然后需要创建一个Formdata对象 获取file文件的内容都是通过request.FILES.get()'''
总结:
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',它会自动转换成对象
contentType前后端传输数据编码格式**
contentType前后端传输数据编码格式 form表单 默认的提交数据的编码格式是urlencoded urlencoded username=admin&password=123这种就是符合urlencoded数据格式 django后端针对username=admin&password=123的urlencoded数据格式会自动解析 将结果打包给request.POST 用户只需要从request.POST即可获取对应信息 formdata django后端针对formdata格式类型数据 也会自动解析 但是不会方法request.POST中而是给你放到了request.FILES中 ajax ajax默认的提交数据的编码格式也是urlencoded username=jason&password=123 总结:django后端针对不同的编码格式数据 会有不同的处理机制以及不同的获取该数据的方法 """ 前后端在做数据交互的时候 一定一定要表明你所发的的数据到底是什么格式 前段后交互 你不能骗人家 你的数据时什么格式 你就应该准确无误告诉别人是什么格式
序列化组件
视图层
from app01 import models from django.core import serializers def ser(request): user_queryset = models.Userinfo.objects.all() #方式一# 自行封装成列表套字典 # user_list = [] # 自行封装成列表套字典 # for user_obj in user_queryset: # user_list.append( # {'username': user_obj.username, # 'password': user_obj.password, # 'gender': user_obj.get_gender_display} # ) # 方式二-用模块处理 res = serializers.serialize('json', user_queryset) print(res) return render(request, 'ser.html', locals())
模板层
<!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> <p>{{ res }}</p> # 模块处理,直接将所有信息封装到一个个字典中,方式二 #以下对应的是方式一 {#<p>{{ user_list }}</p> #列表里面套字典#} {#{% for foo in user_list %}#} {# <p>{{ foo.username }}</p>#} {# <p>{{ foo.password }}</p>#} {# <p>{{ foo.gender }}</p> # 字典取值#} {#{% endfor %}#} </body> </html>
ajax + sweetalert
模型层
<!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> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script> {% load static %} <link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}"> <script src="{% static 'dist/sweetalert.min.js' %}"></script> <style> div.sweet-alert h2 { padding-top: 10px; } </style> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <h2>数据展示</h2> <table class="table table-hover table-striped table-bordered"> <thead> <tr> <th>序号</th> <th>用户名</th> <th>密码</th> <th>性别</th> <th>操作</th> </tr> </thead> <tbody> {% for user_obj in user_queryset %} <tr> <td>{{ forloop.counter }}</td> <td>{{ user_obj.username }}</td> <td>{{ user_obj.password }}</td> <td>{{ user_obj.get_gender_display }}</td> <td> <a href="#" class="btn btn-primary btn-sm">编辑</a> <a href="#" class="btn btn-danger btn-sm cancel" delete_id="{{ user_obj.pk }}">删除</a> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> <script> $('.cancel').click(function () { var $btn = $(this); swal({ title: "你确定要删吗?", text: "你要是删了,你就准备好跑路吧!", type: "warning", showCancelButton: true, confirmButtonClass: "btn-danger", confirmButtonText: "对,老子就要删!", cancelButtonText: "算了,算了!", closeOnConfirm: false, showLoaderOnConfirm: true }, function(){ $.ajax({ url:'', type:'post', data:{'delete_id':$btn.attr('delete_id')}, success:function (data) { if (data.code==1000){ swal(data.msg, "你可以回去收拾行李跑路了.", "success"); // 1.直接刷新页面 {#window.location.reload()#} // 2.通过DOM操作 实时删除 $btn.parent().parent().remove() }else{ swal("发生了未知错误!", "我也不知道哪里错了.", "info"); } } }); }); }) </script> </body> </html>
视图层
""" 当你是用ajax做前后端 交互的时候 你可以考虑返回给前端一个大字典 """ import time from django.http import JsonResponse def sweetajax(request): if request.method == 'POST': back_dic = {"code":1000,'msg':''} delete_id = request.POST.get('delete_id') models.Userinfo.objects.filter(pk=delete_id).delete() back_dic['msg'] = '后端传来的:真的被我删了' time.sleep(3) return JsonResponse(back_dic) user_queryset = models.Userinfo.objects.all() return render(request,'sa.html',locals())