内容概览
- 正反向查询进阶操作
- 聚合查询
- 分组查询
- F与Q查询
- ORM查询优化
- 事务操作
- 模型层常见字段
- ORM常见字段参数
- 多对多三种创建方式
正反向查询进阶操作
"""不使用给出具体条件的表作为主体查找"""
# 1.查询主键为1的书籍对应的出版社名称及书名
res = models.Publish.objects.filter(book__pk=1).values('name', 'book__title') # 过滤条件中也支持使用正反向查询,反向查询使用表名小写
# 2.查询主键为3的书籍对应的作者姓名及书名
res = models.Author.objects.filter(book__pk=3).values('name', 'book__title')
# 3.查询jason的作者的电话号码和地址
res = models.AuthorsDetail.objects.filter(author__name='jason').values('phone', 'address')
# 4.查询南方出版社出版的书籍名称和价格
res = models.Book.objects.filter(publish_name='南方出版社').values('title', 'price') # 正向查询使用字段名
# 5.查询jason写过的书的名称和日期
res = models.Boos.objects.filter(authors__name='jason').values('title', 'publish_time')
# 6.查询电话是111的作者姓名和年龄
res = models.Author.objects.filter(author_detail__phone=111).values('name', 'age')
# 7.查询主键为1的书籍对应的作者电话号码
res = models.Author.objects.filter(book__pk=1).values('author_detail__phone')
"""可以从任意数据查到直接或者间接关联的数据"""
res = models.AuthorDetail.objects.filter(author__book__pk=1).values('phone')
聚合函数
"""使用聚合函数前需要先导入"""
from django.db.models import Max, Min, Sum, Avg, Count
"""在没有分组前想要使用聚合函数需要关键字aggregate"""
res = models.Book.objects.aggregate(Max('price')) # 获取最大值
res = models.Book.objects.aggregate(Min('price')) # 获取最小值
res = models.Book.objects.aggregate(Sum('price')) # 求和
res = models.Book.objects.aggregate(Avg('price')) # 平均值
res = models.Book.objects.aggregate(Count('pk')) # 统计个数
分组查询
分组有个一特性可能会导致报错,既只能够直接获取分组的字段,其他字段需要使用方法;
将sql_mode中only_full_group_by配置移除即可取消该特性
# 统计每本书的作者个数
res = models.Book.objects.annotate(author_num=Count('authors__pk')).values('author_num', 'title')
"""
在分组前不写条件会将一个个数据分组
models.Book.objects.annotate()
想要按照某个字段分组需要先指定字段
models.Book.objects.values('price').annotate() 按照价格分组
"""
# 统计出每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(min_price=Min('book__price')).values('min_price')
# 统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count('authors__pk')).filter(author_num__gte=2).values('title', 'author_num')
# 查询各个作者出的书的总价格
res = models.Author.objects.annotate(total_price=Sum('book__price')).values('name', 'total_price')
F与Q查询
- F查询:查询条件不是自定义而是来自于表中其他字段
# 使用前也需要先导入
from django.db.models import F
# 1.查询库存数大于卖出数的书籍
res = models.Book.objects.filter(storage_num__gt=F('sale_num'))
# 2.将所有书籍的价格上涨1000块
models.Book.objects.update(price=F('price') + 1000)
# 3.将所有书籍名称加上爆款后缀
"""上边方法针对字符串数据无法直接拼接"""
from django.db.models.functions import Concat
from django.db.models import Value
models.Book.objects.update(title=Concat(F('title'),Value('爆款')))
- Q查询:可以改变filter括号内多个条件之间的逻辑运算符
from django.db.models import Q
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查询还可以让字符串也能作为查询条件"""
q_obj = Q() # 先创建Q对象
q_obj.children.append(('pk', 1))
q_obj.children.append(('publish_id', 3))
res = models.Book.objects.filter(q_obj) # 直接将对象当做查询条件即可
ORM查询优化
"""可以先将配置查看SQL代码的配置文件配好"""
django orm自带limit分页,以减轻数据库以及服务端的压力
django orm默认都是惰性查询,只有当orm语句在后续的代码中真正要使用到的时候才会执行
res = model.Book.objects.all() # 不会执行SQL语句
print(res) # 只有在使用到的时候才会执行SQL语句
# only:会将括号内填写的字段封装成数据对象,对象在点击其中的字段的时候不会在从数据库查询;但是也可以点击括号内没有填写的字段,查询括号内没有的字段会走数据库查询
res = models.Book.objects.only('title', 'price')
for obj in res:
print(obj.title)
print(obj.price)
print(obj.publish_time) # 查询没有封装的字段会从数据库查询
# defer:defer与only的作用相反,会将除括号外的字段封装,点击括号内的字段会从数据库中查询
res = models.Book.objects.defer('title', 'price')
for obj in res:
print(obj.title)
print(obj.price)
print(obj.publish_time)
# select_related: 括号内只能接收外键字段(一对一、一对多),会自动连表并封装成数据对象,在点击数据对象中有的字段时就不会再从数据库中查找
res = models.Book.objects.select_related('authors')
for obj in res:
print(obj.publish.name)
# prefetch_related:与select_related的差别在于底层使用的是子查询,将查询之后的结果封装到数据对象
res = models.Book.objects.prefetch_related('authors')
for obj in res:
print(obj.publish.name)
"""select_related与prefetch_related的使用场景不同,占用的资源也不同"""
事务操作
使多个SQL语句要么同时成功,要么都不成功
# 先导入模块
from django.db import transaction
# 使用上下文管理器
try: # 如果orm语句有报错则捕获
with transaction.atomic:
pass # orm语句
except Exception as e:
print(e)
模型层常见字段
AutoField() # int自增
CharField() # varchar
IntegerField() # int
BigIntegerField() # bigint
DateField() # 日期格式
DateTimeField() # 年月日时分秒
DecimalField() # decimal小数
EmailField() # 邮箱格式
BooleanField() # 传布尔值,保存为0或1
TextField() # 存储大段文本
FileField() # 存储文件数据,自动找指定位置存储,字段存储具体位置
ForeignKey()
ManyToManyField()
OneToOneField()
"""ORM还支持自定义字段"""
class MyCharField(models.Field):
def __init__(self, max_length, *args, **kwargs):
self.max_length = max_length
super().__init__(max_length=max_length, *arge, **kwargs)
def db_type(self, connection):
return f'char({self.max_length})'
info = MyCharField(max_length=32)
ORM常见字段参数
max_length 最大字符长度
verbose_name 给字段起别名
auto_now 每次更新数据都会修改为当前时间
auto_now_add 记录创建时的时间
null 设置当前字段是否能为空
default 设置当前字段默认值
max_digits,decimal_places 一般配合DecimalField使用,表示整数与小数占多少位
unique 当前字段是否是唯一
db_index 给字段建立索引
choices 提前列举出数据,添加数据时只需要选择与之对应的数据即可
class UserInfo(models.Model):
username = models.CharField(max_length=32)
gender_choice = (
(1, '男'),
(2, '女'),
(3, '保密')
)
gender = models.IntegerField(choices=gender_choice)
# 获取对应数据要使用数据对象.get_gender_display()
to 指定绑定哪张表
to_field 指定绑定的字段
related_name 替代原来反向查询时使用的'表名小写_set'
on_delete:
1. models.CASCADE:级联操作,主表中的一条数据删除,与之相关联的数据都被删除
2. models.SET_NULL:设置为空,主表中的一条数据删除,与之相关联的数据都设置为null(定义外键时需要设定null=True)
3. models.PROTECT:主表中的一条数据删除,表中相关字段受保护,不允许删除
4. models.SET_DEFAULT:主表中的一条数据被删除,与之相关联的数据都设置为默认值(定义外键时需要设置默认值)
5. models.SET():主表中的一条数据被删除,与之相关联的数据设置为括号内的值
6. models.DO_NOTHING:什么都不做,一切看数据库级别的约束(数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似)
多对多三种创建方式
1. 自动创建
authors = models.ManyToManyField(to='Autor')
第三张表自动创建,但是第三张表扩展性差
2. 手动创建
class Book2Author(models.Model):
book_id = models.ForeignKey(to='Book')
author_id = models.ForeigKey(to='Author')
手动创建第三张表,但是无法使用正反向查询以及多对多四个方法
3. 半自动创建
class Book(models.Model):
authors = models.ManyToManyField(to='Author',
through='Book2Author',
through_fields=('book_id', 'author_id')
)
class Author(models.Model):
pass
class Book2Author(models.Model):
book_id = models.ForeignKey(to='Book')
author_id = models.ForeignKey(to='Author')
扩展性强且支持正反向操作,依然无法使用多对多四个方法
4466

被折叠的 条评论
为什么被折叠?



