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())