正反向查询进阶操作

1.查询主键为1的书籍对应的出版社名称及书名
    res = models.Publish.objects.filter(book__pk=1).values('name','book__title')
    print(res)

2.查询主键为3的书籍对应的作者姓名及书名
    res = models.Author.objects.filter(book__pk=1).values('name', 'book__title')
    print(res)

3.查询jason的作者的电话号码和地址
    res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','addr')
    print(res)

4.查询南方出版社出版的书籍名称和价格
    res = models.Book.objects.filter(publish__name='南方出版社').values('title','price')
    print(res)

5.查询jason写过的书的名称和日期
    res = models.Book.objects.filter(authors__name='jason').values('title','publish_time')
    print(res)

6.查询电话是110的作者姓名和年龄
    res = models.Author.objects.filter(author_detail__phone=110).values('name','age')
    print(res)

7.查询主键为1的书籍对应的作者电话号码
    res = models.AuthorDetail.objects.filter(author__book__pk=1).values('phone')
    print(res)
    res = models.Author.objects.filter(book__pk=1).values('author_detail__phone')
    print(res)

聚合查询

没有分组之前如果单纯的使用聚合函数 需要用到关键字:aggregate

聚合函数:max、min、sum、avg、count
eg:
    from django.db.models import Max, Min, Avg, Sum, Count  # 导入集合函数
    res = models.Book.objects.aggregate(Max('price'), Min('price'), Sum('price'), Avg('price'), Count('pk'))
    print(res)

分组查询

"""
需要用到关键字annotate 相当于mysql中grouo_by
分组有一个特性 默认只能够直接获取分组的字段 其他字段需要使用方法
我们也可以忽略掉该特性 将sql_mode中only_full_group_by配置移除即可
	set global sql_mode = 'STANS_ARANS_TABLES'
filter在annotate前面相当于是mysql中的where 在annotate后面则是having
"""
示例1:统计每一本书的作者个数
    res = models.Book.objects.annotate(author_num=Count('authors__pk')).values('title', 'author_num')
    print(res)

示例2:统计出每个出版社卖的最便宜的书的价格
    res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name', 'min_price')
    print(res)

示例3:统计不止一个作者的图书
    res = models.Book.objects.annotate(author_num=Count('authors__pk')).filter(author_num__gt=1).values('title','author_num')
    print(res)

示例4:查询各个作者出的书的总价格
    res = models.Author.objects.annotate(book_sum_price = Sum('book__price')).values('name','book_sum_price')
    print(res)

res1 = models.Book.objects.values('publish_id').annotate(book_num=Count('pk')).values('publish_id','book_num')
print(res1)
"""
1.按照整条数据分组
	models.Book.objects.annotate()  按照一条条书籍记录分组
2.按照表中某个字段分组()
	models.Book.objects.values('title').annotate()  按照annotate之前values括号中指定的字段分组 annotate后的values是具体字段对应的值
"""

F与Q查询

F查询

查询条件不是自定义的而是来自于表中其他字段

from django.db.models import F
1.查询库存数大于卖出数的书籍
    res = models.Book.objects.filter(storage_num__gt=F('sale_num'))
    print(res)
2.将所有书籍的价格上涨1000块
    models.Book.objects.update(price=F('price') + 1000)
3.将所有书籍名称加上爆款后缀
    models.Book.objects.filter(pk=5).update(title=F('title') + '爆款')  # 针对字符串数据无法直接拼接 会报错 需要使用下述方式
from django.db.models.functions import Concat
from django.db.models import Value
    ret3 = models.Book.objects.filter(pk=5).update(title=Concat(F('title'), Value('爆款')))
Q查询

可以改变filter括号内多个条件之间的逻辑运算法

from django.db.models import Q
res = models.Book.objects.filter(pk=1,publish_id=3)  # 默认是and关系
res = models.Book.objects.filter(Q(pk=1),Q(publish_id=3))  # 逗号分割还是and关系
res = models.Book.objects.filter(Q(pk=1)|Q(publish_id=3))  # 管道符是or关系
res = models.Book.objects.filter(~Q(pk=1)|Q(publish_id=3))  # 波浪号是not关系

还可以将查询条件的字段改为字符串形式

q_obj = Q()
q_obj = connector = 'or'  # Q对象默认的多个条件也是and关系 可以修改成or
q_obj = children.append(('pk',2))  # 第一个字段是字符串类型的字段名 第二个是一个具体的数据值 添加的是列表和元组的都可以
q_obj = children.append(('publish_id',2))  # 可以不停的往里添加
res = models.Book.objects.filter(q_obj)  # 支持用filter筛选 直接将Q对象到里面

ORM查询优化

django orm默认都是惰性查询
	当orm的语句在后续的代码中真正需要使用的时候才会执行
django orm自带limit分页
	减轻数据库端以及服务端的压力
  
res = models.Book.objects.only('title','price')
for obj in res:
     print(obj.title)
     print(obj.price)
     print(obj.publish_time)
"""
    only会将括号内填写的字段封装成一个个数据对象 对象在点击的时候不会再走数据库查询
    但是对象也可以点击括号内没有的字段 只不过每次都会走数据库查询
"""
res = models.Book.objects.defer('title', 'price')
for obj in res:
    print(obj.title)
    print(obj.price)
    print(obj.publish_time)
"""
defer与only刚好相反 
    数据对象点击括号内出现的字段 每次都会走数据库查询
    数据对象点击括号内没有的字典 不会走数据库查询
"""
 
'''ORM查询优化之select_related与prefetch_related'''
res = models.Book.objects.all()
for obj in res:
     print(obj.publish.name)  # 频繁走数据库查询

res = models.Book.objects.select_related('authors')
"""
    select_related括号内只能接收外键字段(一对多 一对一) 自动连表 得出的数据对象在点击表中数据的时候都不会再走数据库查询
"""
for obj in res:
     print(obj.publish.name)
"""
    prefetch_related底层其实是子查询 将查询之后的结果也一次性封装到数据对象中 用户在使用的时候是感觉不出来的
"""
res = models.Book.objects.prefetch_related('publish')
for obj in res:
    print(obj.publish.name)

事务操作

事务:ACID
	原子性:不可分割的最小单位
	一致性:跟原子性是相辅相成
	隔离性:事务之间互相不干扰
	持久性:事务一旦确认永久生效
事务隔离级别
	脏读 幻读 不可重复读
原生SQL
	start transaction 开启事务
	rollback 事务回滚
	commit 提交事务
	savepoint 保存点
Django开启事务
from django.db import transaction  # 导入事务
try:  # 异常捕获
    with transaction.atomic():
        pass  # 多条ORM语句
except Exception as e:
        print(e)

模型层常见字段

1.AutoField()
	int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列
2.CharField()
	字符类型 必须提供max_length参数 max_length表示字符长度
3.IntegerField()
	一个整数类型,范围在 -2147483648 to 2147483647(一般不用它来存手机号(位数也不够),直接用字符串存)
4.BigIntegerField()
	bigint自增列,必须填入参数 primary_key=True
5.DateField()
	日期字段 日期格式  YYYY-MM-DD,相当于Python中的datetime.date()实例
6.DateTimeField()
	日期时间字段 格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。
7.DecimalField()
	10进制小数
	参数:
		max_digits,小数总长度
		decimal_places,小数位长度
8.EmailField()
	字符串类型,Django Admin以及ModelForm中提供验证机制
9.BooleanField()
	传布尔值存数字0或1
10.TextField()
	存储大段文本 没有数字限制
11.FileField()
	存储文件数据  自动找指定位置存储 字段存具体路径
12.ForeignKey()
	一对多字段
13.OneToOneField()
	一对一字段
14.ManyToManyField()
	多对多字段

ORM常见字段参数

1.max_length
	长度
2.verboses_name
	字段的注释
3.max_digits
	小数总长度
4.decimal_places
	小数位长度
5.null
	用于表示某个字段可以为空
6.unique
	如果设置为unique=True 则该字段在此表中必须是唯一的
7.db_index
	如果db_index=True 则代表着为此字段设置索引
8.default
	为该字段设置默认值

DateField和DateTimeField
9.auto_now_add
	配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库10.auto_now
	配置上auto_now=True,每次更新数据记录的时候会更新该字段

11.to
	设置要关联的表
12.to_field
	设置要关联的字段
13.related_name
	反向操作是 使用该字段名 类型起别名

choices

当字段数据的可能性是可以完全列举出来的时候 应该考虑使用该参数

eg:性别、学历、成绩

class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    gender_choice = (
            (1, '男性'),
            (2, '女性'),
            (3, '其他'),)
    gender = models.IntegerField(choices=gender_choice)
userinfo_obj.get_gender_display()

on_delete
当删除关联表中的数据时,当前表与其关联的行的行为

1、models.CASCADE
	级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除
2、models.SET_NULL
	当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空
3、models.PROTECT
	当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除
4、models.SET_DEFAULT
	当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值
5、models.SET()
	当主表中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数
6、models.DO_NOTHING
	什么都不做,一切都看数据库级别的约束,注数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似

多对多三种创建方式

方式一:自动创建
class Book(models.Model):
    name = models.CharField(max_length=32)
    authors = models.ManyToManyField(to='Author')
class Author(models.Model):
    name = models.CharField(max_length=32)
"""
优点:第三张表自动创建
缺点:第三张表扩展性差
"""
方式二:手动创建
class Book(models.Model):
    name = models.CharField(max_length=32)
    
class Author(models.Model):
    name = models.CharField(max_length=32)
  
class Book2Author(models.Model):
    book_id = models.ForeignKey(to='Book')
    author_id = models.ForeignKey(to='Author')
"""
优点:第三张表扩展性强
缺点:无法使用正反向查询以及多对多四个方法(add、updete、set、clear)
"""
方式三:半自动创建
class Book(models.Model):
    name = models.CharField(max_length=32)
    authors = models.ManyToManyField(to='Author',
                through='Book2Author',
                through_fields=('book_id','author_id'))
    
class Author(models.Model):
    name = models.CharField(max_length=32)
    books = models.ManyToManyField(to='Book',                                through='Book2Author',                                  through_fields=('author','book'))
    
class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')
"""
优点:扩展性强并且支持正反向查询
缺点:无法使用多对多四个方法(add、updete、set、clear)
"""

Ajax简介

  • AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据

    • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求
    • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求
    • AJAX除了异步的特点外,还有一个就是:浏览器页面局部刷新(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
一、Ajax基础语法
$.ajax({
    url:'',   // 控制数据的提交地址
    type:'',  // 控制请求方式(默认get请求)
    data:{},  // 组织提交的数据
    success:function(形参){
        //异步回调函数
    }
})
二、数据编码格式(ContentType)
格式一:application/x-www-form-urlencoded(urlencoded)
	数据格式: name=jason&pwd=123&hobby=read
	django后端统一处理到request.POST中
    
格式2:multipart/form-data
	数据格式: 无法查阅
	django后端自动将文件数据处理到request.FILES 普通键值对数据request.POST

格式3:application/json
	数据格式: json格式
	django后端不会处理 在request.body中存储(bytes类型) 自己处理

语法注意事项
	data: JSON.stringify({'name':'jason','pwd':123}),
	contentType: 'application/json',
"""
form表单是没有办法发送json格式数据的
	只能使用格式1和格式2
ajax默认的编码格式也是urlencoded
	上述三种三种格式都能使用
"""
三、基于Ajax上传文件

ajax发送文件需要借助于js内置对象FormData

$('#d3').click(function () {
	// 1.需要先利用FormData内置对象
	let formData = new FormData();
	// 2.添加普通数据
	formData.append('username',$('#d1').val())
	// 3.添加文件数据
	formData.append('file', $('#d2')[0].files[0])
	// 4.发送ajax请求
	$.ajax({
        url:'',
        type:'post',
        data:formData,  // 直接将对象放在data后面即可
        contentType:false,  // 不使用任何编码 django后端能够自动识别formdata对象
        processData:false,  // 告诉你的浏览器不要对你的数据进行任何处理
        success:function (args) {
            
        }
	})
})
"""
浏览器请求头为
	Content-Type:
	multipart/form-data; boundary=—-WebKitFormBoundaryA5O53SvUXJaF11O2
"""
四、回调函数
后端跟ajax交互 不应该再返回页面 通常情况下都是返回json格式数据
前端针对HttpResponse和JsonResponse返回的json格式数据处理策略不同
	前者不会自动反序列化 而后者会自动反序列化
	如果想让前者也自动反序列化可以添加一个固定的参数
        	dataType:'JSON'
五、Ajax提交json格式数据
$("#ajax_test").click(function () {
    var dic={'name':'lqz','age':18}
    $.ajax({
        url:'',
        type:'post',
        contentType:'application/json',  //一定要指定格式 contentType: 'application/json;charset=utf-8',
        data:JSON.stringify(dic),    //转换成json字符串格式
        success:function (data) {
            console.log(data)
        }

    })

})

django内置的序列化

把对象序列化成json字符串

from django.core import serializers

def ser(request):
    #拿到用户表里面的所有的用户对象
    user_list=models.User.objects.all()
    #导入内置序列化模块
    from django.core import serializers
    #调用该模块下的方法,第一个参数是你想以什么样的方式序列化你的数据
    res=serializers.serialize('json',user_list)
    return HttpResponse(res)

image

 posted on 2022-09-06 21:22  Joker_Ly  阅读(229)  评论(0)    收藏  举报