学习内容概要
正反向查询进阶操作
聚合查询
分组查询
F与Q查询
ORM查询优化
ORM常见字段类型
ORM常见字段参数
ORM事物操作
多对多三种创建方式详细
内容详细
正反向查询进阶操作
res = models.Publish.objects.filter (book__pk=1 ).values('name' ,'book__title' )
res = models.Author.objects.filter (book__pk=1 ).values('name' , 'book__title' )
res = models.AuthorDetail.objects.filter (author__name='jason' ).values('phone' ,'addr' )
res = models.Book.objects.filter (publish__name='南方出版社' ).values('title' ,'price' )
res = models.Book.objects.filter (authors__name='jason' ).values('title' ,'publish_time' )
res = models.Author.objects.filter (author_detail__phone=110 ).values('name' ,'age' )
res = models.AuthorDetail.objects.filter (author__book__pk=1 ).values('phone' )
res = models.Author.objects.filter (book__pk=1 ).values('author_detail__phone' )
print (res)
聚合查询
1、MySQL中的聚合函数:
2.关键字:aggregate
from django.db.models import Max,Min,Sum,Avg,Count
res = models.Book.objects.aggregate(Max('price' ),Min('price' ),Sum('price' ),Avg('price' ),Count('PK' ))
print (res)
分组查询
"""
分组有一个特性 默认只能够直接获取分组的字段 其他字段需要使用方法
我们也可以忽略掉该特性 将sql_mode中only_full_group_by配置移除即可
"""
'''分组查询'''
res = models.Book.objects.annotate(author_num=Count('authors__pk' )).values('title' , 'author_num' )
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括号中指定的字段分组
"""
res = models.Publish.objects.annotate(min_price=Min('book__price' )).values('name' , 'min_price' )
'''filter在annotate前面则是where 在annotate后面则是having'''
res = models.Book.objects.annotate(author_num=Count('authors__pk' )).filter (author_num__gt=1 ).values('title' ,'author_num' )
res = models.Author.objects.annotate(book_sum_price = Sum('book__price' )).values('name' ,'book_sum_price' )
print (res)
F查询
1、F查询:查询条件不是自定义的而是来自于表中其他字段
from django.db.models import F
res = models.Book.objects.filter (storage_num__gt=F('sale_num' ))
models.Book.objects.update(price=F('price' ) + 1000 )
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查询
1、Q查询:可以改变filter括号内多个条件之间的逻辑运算符
2、Q查询:还可以将查询条件的字段改为字符串形式
'''Q查询:可以改变filter括号内多个条件之间的逻辑运算符'''
from django.db.models import Q
res = models.Book.objects.filter (pk=1 , publish_id=3 )
res = models.Book.objects.filter (Q(pk=1 ), Q(publish_id=3 ))
res = models.Book.objects.filter (Q(pk=1 ) | Q(publish_id=3 ))
res = models.Book.objects.filter (~Q(pk=1 ) | Q(publish_id=3 ))
print (res.query)
'''Q查询:还可以将查询条件的字段改为字符串形式'''
q_obj = Q()
q_obj.connector = 'or'
q_obj.children.append(('pk' , 1 ))
q_obj.children.append(('publish_id' , 3 ))
res = models.Book.objects.filter (q_obj)
print (res)
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.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
1. 原子性
2. 一致性
3. 隔离性
4. 持久性
事务隔离级别:脏读 幻读 不可重复读 ...
原生SQL: start transaction\rollback\commit\savepoint
from django.db import transaction
try :
with transaction.atomic():
pass
except Exception as e:
print (e)
模型层常见字段(models.py)
AutoField()
CharField()
IntegerField()
BigIntegerField()
DateField()
DateTimeField()
DecimalField()
EmailField()
BooleanField()
传布尔值存数字0 或1
TextField()
存储大段文本
FileField()
存储文件数据 自动找指定位置存储 字段存具体路径
ForeignKey()
OneToOneField()
ManyToManyField()
ORM还支持自定义字段
class MyCharField (models.Field):
def __init__ (self, max_length, *args, **kwargs ):
self.max_length = max_length
super ().__init__(max_length=max_length, *args, **kwargs)
def db_type (self, connection ):
return 'char(%s)' % self.max_length
info = MyCharField(max_length=32 )
ORM常见字段参数
max_length
verboses_name
auto_now
auto_now_add
null
default
max_digits
decimal_places
unique=True
db_index=True
choices
当字段数据的可能性是可以完全列举出来的时候 应该考虑使用该参数
性别
学历
成绩
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()
to
to_field
related_name
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相似
多对多三种创建方式
1. 自动创建
authors = models.ManyToManyField(to='Author' )
优点:第三张表自动创建
缺点:第三张表扩展性差
2. 手动创建
class Book (models.Model):
pass
class Author (models.Model):
pass
class Book2Author (models.Model):
book_id = models.ForeignKey(to="Book" )
author_id = models.ForeignKey(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" )
优点:扩展性强并且支持正反向查询
缺点:无法使用多对多四个方法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)