django
- 2020 年 11 月 25 日
- 筆記
1 ajax基本语法
test.html
view.py
def ab_ajax(request):
if request.method == 'POST':
i1 = request.POST.get('i1')
i2 = request.POST.get('i2')
res = int(i1) + int(i2)
return HttpResponse(res)
return render(request, 'test.html')
2 前后端传输数据的编码格式
# 1 我们主要研究post请求数据的编码格式
"""
get请求数据就是直接放在url后面的,如:
url?username=xpj&password=123
"""
# 2 前后端传输数据的三种格式
"""
1 urlencoded: form表单提交数据格式
2 multipart/formdata: 针对文件格式,封装到request.FILES里
3 json
"""
# 3 可以朝后端发送post请求的方式
"""
1 form表单
默认的数据编码格式是urlencoded
数据格式:username=xpj&password=123
django后端针对urlencoded编码格式的数据会自动帮你封装到request.POST中
如果你把编码格式改为formdata,那么针对普通的键值对还是解析到request.POST中,而针对文件会解析到request.FILFES中
form表单是没有办法传输json个是数据的
2 ajax请求
默认的数据编码格式是urlencoded
数据格式:username=xpj&password=123
django后端针对urlencoded编码格式的数据会自动帮你封装到request.POST中
"""
3 ajax发送json格式数据
'''
前后端传输数据的时候一定要确保编码格式跟数据格式是一致的
如果传输的是json格式的数据request.post里是找不到的
request.is_ajax(),判断当前请求是否是ajax请求,返回bool值
django针对json格式的数据不会做任何处理,需要自己处理
解决方法:
1.json_bytes = request.body
json_str = json_bytes.decode('utf-8')
json_dict = json.loads(json_str)
2.json_dict = json.loads(json_bytes)
'''
#1 ajax改变发送的编码格式
$.ajax({
'''''
cententType: 'application/json', //指定编码格式
''''''
})
4 ajax发送文件
'''
ajax发送文件需要借助js内置对象FormData
'''
<script>
$('#d4').on('click', function (){
// 1 需要先利用FormData内置对象生成一个对象
let formdata_obj = new FormData()
// 2 添加普通的键值对
formdata_obj.append('username', $('#d1').val());
formdata_obj.append('password', $('#d2').val());
// 3 添加文件对象,$('#d3')是jquery对象, $('#d3')[0]转成原生js对象标签对象, $('#d3')[0].files[0]拿到用户传进来的文件对象
formdata_obj.append('myfile', $('#d3')[0].files[0])
// 4 将对象基于ajax发送给后端
$.ajax({
url: '',
type: 'post',
data: formdata_obj, //直接将对象放在data后面即可
//ajax发送文件必须要指定的两个参数
contentType: false, // 不需要使用任何编码,django后端能够自动识别formdata对象
processData: false, // 告诉你的游览器不要对你的数据进行任何处理
success: function (args){
alert(1)
}
})
})
</script>
5 ajax结合sweetalert实现二次确认
<p>
<button class="del" delete_id="{{ user_obj.pk }}"></button>
</p>
<script>
$('.del').on('click', function (){
alert($(this).attr('delete_id')) //this拿到的是当前标签.attr拿到标签的属性
})
</script>
# bulk_create()
book_list = []
for i in range(100000):
book_obj = models.Book.objects.all()
book_list.append(book_list)
models.Book.objects.bulk_create(book_list)
return render(request, 'ab_pl.html', locals())
# 1 对比用户名和密码是否正确
user_obj = auth.authenticate(request, username=username, password=password) # 括号内必须同时传入request, 用户名和密码
print(user_obj) # 用户对象 jason
print(user_obj.username) # jason
print(user_obj.password) # 密文
# 2 保存用户状态
auth.login(request, user_obj) # 执行了该方法,你可以在任何地方通过request.user获取当前登录的对象
# 3 判断当前用户是否登录
request.user.is_authenticated()
# 4 获取当前登录用户
request.user
# 5 校验用户是否登录装饰器
from django.contrib.auth.decorators import login_required
# 局部配置,用户没有登录会跳转到login页面
2 auth模块表拓展
class UserInfo(AbstractUser):
"""
如果继承了AbstractUser
那么在执行数据库迁移命令的时候auth_user表就不会再创建出来了
UserInfo表中会出现auth_user所有的字段外加自己拓展的字段
"""
phone = models.BigIntegerFeild()
"""
前提:
1. 必须在auth_user没有被创建之前继承
2. 必须在settings.py里声明
AUTH_USER_MODEL = 'app01.UserInfo'
3. 继承的类不能出现同名字段
"""
1 单表操作
测试脚本
models.py
class User(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
register_time = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.name
test.py
# 去manage.py文件中复制前四行代码,粘贴进test.py文件中并写入两行代码,即可在单个py文件中进行测试
import os
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangoProject3.settings')
# 这两行是新加入的
import django
django.setup()
2 必知必会13条
# 1 create()
models.User.objects.create(name='kerwin', age=24)
# 2 delete()
models.User.objects.filter(pk=2).delete()
(1, {'app01.User': 1}) # 返回剩余个数
# 3 update()
models.User.objects.filter(pk=1).update(age=18)
1 # 修改成功返回1
# 4 filter()
models.User.objects.filter(pk=1)
<QuerySet [<User: xpj>]> # 拿到的是queryset,不存在返回空
# 5 fisrt()
models.User.objects.filter(pk=1).first()
<User: xpj> # 拿到对象
# 6 get()
models.User.objects.get(pk=1)
<User: xpj> # 拿到的是User对象,但是如果不存在的话会报错
# 7 values()
models.User.objects.values('name') # 字段查询
<QuerySet [{'name': 'xpj'}]> # 列表套字典的queryset
# 8 values_list()
models.User.objects.values_list('name', 'age')
<QuerySet [('xpj', 24)]> # 列表套元组的queryset
# 9 distinct()
models.User.objects.values('name', 'age').distinct()
# 10 order_by()
models.User.objects.order_by('age')
models.User.objects.order_by('-age') # 降序
# 11 count()
models.User.objects.filter(pk=1).count()
# 12 reverser() # 反转
# 13 exists() # 存在
# 14 exclude() #
3 双下划线查询
#1 年龄大于35岁
models.User.objects.filter(age__gt=35)
#2 年龄小于35岁
models.User.objects.filter(age__lt=35)
#3 年龄大于等于,小于等于35岁
models.User.objects.filter(age__gte=35)
models.User.objects.filter(age__lte=35)
#4 年龄是18,32,40
models.User.objects.filter(age__in=[18,32,40])
#5 年龄是18到40岁之间的
models.User.objects.filter(age__range=[18,40])
2 多表操作
1 多表准备
models.py
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2)
publish_date = models.DateTimeField(auto_now_add=True)
publish = models.ForeignKey(to='Publish', on_delete=models.CASCADE)
authors = models.ManyToManyField(to='Author')
class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=64)
email = models.EmailField()
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
author_detail = models.OneToOneField(to='AuthorDetail', on_delete=models.CASCADE)
class AuthorDetail(models.Model):
phone = models.BigIntegerField()
addr = models.CharField(max_length=64)
2 一对多
# 1 增
# 直接写id
models.Book.objects.create(title='三国演义', price=123.45, publish_id=1)
# 虚拟字段对象
publish_obj = models.Publish.objects.filter(pk=2).first()
models.Book.objects.create(title='红楼梦', price=66.21, publish_id=publish_obj.pk)
# 2 删
models.User.objects.filter(pk=2).delete()
# 3 改
models.User.objects.filter(pk=1).update(publish_id=3)
3 多对多
# 多对多关系表的增删改查其实就是第三张关系表的增删改查
# 1 通过book表给author表添加作者,通过第三张表
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors # 相当于进入authorsDetail表
book_obj.authors.add(1)
book_obj.authors.add(2,3)
author_obj = models.Author.objects.filter(pk=2).first()
book_obj.author.add(author_obj.pk)
# 2 删
remove(2)
# 3 改
括号内必须传一个可迭代对象
set([1,2])
# 4 清空
clear()
4 正反向概念
# 正向
看外键字段在哪个表,外键字段所在表查外键字段的表就是正向
book--->外键字段在book表--->publish(正向)
# 反向
反之
"""
正向查询按字段
反向查询按表名小写
"""
5 多表的跨表查询
子查询(基于对象的跨表查询)
# 1 查询书籍主键为1的出版社名称
book_obj = models.Book.objects.filter(pk=1).first()
publish_obj = book_obj.publish
publish_obj.name
# 2 查询书籍主键为2的作者
book_obj = models.Book.objects.filter(pk=2).first()
author_obj = book_obj.authors.all() # 结果可能有多个加all
# 3 查询作者为jason的电话号码
author_obj = models.Author.objects.filter(name='jason').first()
author_detail_obj = authos_obj.author_detail
# 4 查询出版社是东方出版社出版的书(反向)
publish_obj = models.Publish.objects.filterr(name='东方出版社').first()
book_obj = publish_obj.book_set.all() # 表名小写_set一般是对对象
# 5 查询作者是jason写过的书(反向)
author_obj = models.Author.objects.filter(name='jason').first()
book_obj = author_obj.book_set.all()
# 6 查询手机号是110的作者姓名
author_detail_obj = models.AuthorDetil.objects.filter(phone=110).first()
author_obj = author_detail_obj.author_set
连表查询(基于双下划线的跨表查询)
# 1 查询jason的手机号和作者姓名
# 正向
phone = models.Author.objects.filter(name='jason').values('author_detail__phone','name')
# 反向
models.AuthorDetail.objects.filter(author__name='jason').values('phone', 'author__name')
# 2 查询书籍主键为1的出版社名称和书的名字
# 正向
models.Book.objects.filter(pk=1).values('title', 'publish__name')
# 反向
models.Publish.objects.filter(book__id=1).values('name', 'book__title')
# 3 查询书籍主键为1的作者姓名
# 正向
models.Book.objects.filter(pk=1).values('authors__name') # 正向查询按字段
# 反向
models.author.objects.filter(book__id=1).values('name')
# 4 查询书籍主键1的作者的手机号
models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
3 聚合查询
aggregate()
# 一般是配合分组一起使用
from app01 import models
from django.db.models import Max, Min, Count, Avg, Sum
models.Book.objects.aggregate(Max('price'), Min('price'), Avg('price'), Count('pk'), Sum('price'))
4 分组查询
-
annotate()
内写聚合函数
-
重点: 只要你写的orm得出的结果是一个queryset对象,那么你就可以无限的.queryset的方法,比如.values, .filter等等
-
values
在前表示group by的字段
-
values
在后表示取某几个字段
-
filter
在前表示where
-
filter
在后表示having
# 1 统计每一本书的作者个数
models.Book.objects.annotate(author_num=Count('authors')).values('author_num') # models后面.什么就按什么分组,author_num是作者个数的别名,一个变量,本来跨表是要authors__id的,但是orm很智能,可以省略__id
models.Book.objects.annotate(author_num=Count('authors__id')).values('author_num')
# 2 统计每个出版社卖的最便宜的书的价格
models.Publish.objects.annotate(min_book_pirce=Min('book__price')).values('min_book_price')
print(res)
# 3 统计不止一个作者的图书
models.Book.objects.annotate(author_num=Count('authors__id')).filter(author_num__gt=1)
# <QuerySet [<Book: Book object>, <Book: Book object>, <Book: Book object>]>
models.Book.objects.annotate(author_num=Count('authors__id')).filter(author_num__gt=1).values('title', 'author_num')
# 4 查询每个作者书的总价格
models.Author.objects.annotate(total_price=Sum('book__price')).values('total_price')
重点: 只要你写的orm得出的结果是一个queryset对象,那么你就可以无限的.queryset的方法,比如.values, .filter等等
5 F查询
# 1 查询卖出数大于库存数的书籍
"""
F能够帮助你直接获取数据表中某个字段在表中对应的数据
"""
from django.db.models import F
models.Book.objects.filter(maichu__gt=F('kucun'))
# 2 将所有书的价格提升50块
models.Book.objects.update(price=F('price')+50)
# 3 将所有书的名称后面加上爆款2个字
"""
在操作字符串的时候F不能直接做到字符串的拼接
"""
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.update(title=Concat(F('title').value('爆款')))
6 Q查询
# 1 查询卖出数大于100或者价格小于600的书籍
models.Book.objects.filter(maichu__gt=100, price__lt=600)
# <QuerySet []> 因为filter内部多个参数是and的关系
7 django中开启事务
"""
原子性
一致性
隔离性
持久性
回滚 roolback
确认
commit
"""
from django.db import transaction
try:
with transaction.atomic():
# with中写的所有orm都属于一个事务
except Exception as e:
print(e)
8 ORM中常用字段和参数
//www.cnblogs.com/Dominic-Ji/p/9203990.html
9 数据库查询优化
# 1 only与defer