Django微讲解(七)

Django微讲解(七)

聚合查询

我们在讲数据库的聚合查询的时候,讲了数据库的聚合函数,常用就是最大值'max'、最小值'min'、求和'sum'、计数'count'
平均值'avg',我们的Django ORM聚合查询使用的也是这些关键字,只不过数据库的聚合函数是需要分组之后才可以使用的,而Django ORM
的聚合函数没有分组也可以使用聚合函数,默认整体的一个表就是一组。
from django.db.models import Max,Min,Count,Sum,Avg
res = models.Book.objects.aggregate(Max('price'))
print(res)
使用聚合查询的关键字是'aggregate'

分组查询

数据库的分组查询使用的是group by关键字,Django ORM使用的关键字是'annotate',ORM在执行分组操作的时候,有的计算机
会报错,报错的话可以去修改'sql_mode',移除'only_full_group_by'即可。
# 1.统计每本书的作者个数
res = models.Book.objects.annotate(auhtor_num=Count('authors__pk')).values('title','auhtor_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_count=Count('authors__pk')).filter(author_count__gte=2).values('title','author_count')
print(res)
# 4.统计每个作者出的书的总价格
res = models.Author.objects.annotate(price_num=Sum('book__price')).values('name','price_num')
print(res)
# 5.统计每个出版社主键值对应的书籍个数
'''
上述四个练习题都是以表为单位分组的,如果想要以表中的某个字段分组,只需要在'annotate'关键字前面点'values'给某个字段进行分组即可
'''
res = models.Book.objects.values('publish_id').annotate(book_num=Count('pk')).values('publish_id','book_num')
print(res)

往已经存在数据的表中添加字段

当表中已经存在数据的情况下,想要在添加额外字段,就需要指定该字段的默认值,或者指定该字段的值可以为null
方式一:
可以给额外添加的字段加一个默认值,关键字是'default'
示例:age = models.IntegerField(default=25)
方式二:
设置额外添加字段的值可以为null
示例:age = models.IntegerField(null=True)
方式三:
可以在迁移命令的提示中直接给默认值

F查询

F可以帮我们取到表中某个字段对应的值来当做我们的筛选条件,而不是自定义常量的条件,实现了动态比较的效果,Django还支
持F对象之间以及F对象与常数之间的加减乘除和取模的操作。
# 1.查询库存大于销量的书籍
from django.db.models import F
res = models.Book.objects.filter(kucun__gt=F('xiaoliang'))
print(res)
# 2.将所有书的价格提升1000块
res = models.Book.objects.update(price=F('price') + 1000)
print(res)
# 3.将所有书的名称后面加上_爆款后缀
'''
想要修改char字段的值,不可以用上述的方法,可以使用下面ORM专门提供的方法
'''
from django.db.models.functions import Concat
from django.db.models import Value,F
models.Book.objects.update(title=Concat(F('title'),Value('_iii')))

Q查询

filter()方法中逗号隔开的条件是'and'的关系,是没有办法直接修改的,所以我们就可以使用Q对象,支持逻辑运算符,'管道
符'(|)就是'or'关系,在Q对象前面加'~'就是'not'的关系。
# 1.查询价格大于20000或者卖出大于1000的书籍
from django.db.models import Q
res = models.Book.objects.filter(Q(price__gt=20000)|Q(xiaoliang__gt=1000))
print(res) # 管道符是or关系
# 2.查询价格小于20000或者库存小于1000的书籍
res = models.Book.objects.filter(~Q(price__gte=20000)|~Q(kucun__gte=1000))
print(res) # ~是not关系
# 3.Q对象进阶用法
q_obj = Q() # Q方法其实是一个类,我们先产生一个q_obj对象
q_obj.connector = 'or' # 默认是and关系,可以改没or
q_obj.children.append(('price__gt',20000))
q_obj.children.append(('kucun__gt',1000))
res = models.Book.objects.filter(q_obj)
print(res)

ORM查询优化

ORM查询默认都是惰性查询,能不消耗数据库资源就不消耗,ORM查询默认自带分页功能,尽量减轻单次查询数据的压力
# only
only会产生对象结果集,对象点括号内出现的字段不会再次查询数据库
res = models.Book.objects.only('title','price')
for obj in res:
print(obj.title)
print(obj.price)
# print(obj.xiaoliang) # 也可以点括号以外的,但是会再次查询数据库,增加了数据库的压力
# defer
defer也会产生对象结果集,对象点括号之外的字段不会再次查询数据库
res = models.Book.objects.defer('title','price')
for obj in res:
print(obj.xiaoliang)
# print(obj.price) # 也可以点括号内的,但是会再次查询数据库,增加数据库的压力
# select_related
select_related括号内只能传外键字段,只能传一对一和一对多字段,不能传多对多字段,内部原理就是直接连表,然后将连
接之后的表中所有的数据全部封装到数据对象中,然后对象就可以通过正反向查询,内部不会再次查询数据库,不会增加数据库的压力。
res = models.Book.objects.select_related('publish')
for obj in res:
print(obj.title)
print(obj.price)
print(obj.publish.name)
print(obj.publish.addr)
# prefetch_related
prefetch_related括号内只能传外键字段,只能传一对一和一对多字段,不能传多对多字段,内部原理是将多次查询之后的结
果封装到数据对象当中,然后对象就可以通过正反向查询,内部不会再次查询数据库,不会增加数据库的压力。
res = models.Book.objects.prefetch_related('publish')
for obj in res:
print(obj.title)
print(obj.price)
print(obj.publish.name)
print(obj.publish.addr)

ORM常见字段

# 1.AutoField
int自增列,必须填入参数 primary_key=True。当model中如果没有自增列,则自动会创建一个列名为id的列。
# 2.IntegerField
整型int
# 3.CharField
字符类型,必须提供max_length参数, max_length表示字符长度,对应的是数据库中的varchar类型,没有设置对应char类型
的字段,但是Django允许我们自定义新的字段。
# 4.DecimalField
10进制小数
# 5.DateField
日期字段,日期格式 YYYY-MM-DD,相当于Python中的datetime.date()实例。
# 6.DateTimeField
日期时间字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相当于Python中的datetime.datetime()实例。
# 7.BigIntergerField
整型bigint
# 8.BooleanField
传布尔值,对应的是01
# 9.TextField
存储大段文本
# 10.FileField
传文件自动保存到指定位置并存文件路径
# 11.EmailField
本质还是varchar类型

ORM重要参数

# 1.primary_key
主键
# 2.max_length
字段最大长度
# 3.verbose_name
注释
# 4.null
是否允许为空
# 5.default
设置默认值
# 6.max_digits
小数总长度
# 7.decimal_places
小数位长度
# 8.unique
如果设置为unique=True 则该字段在此表中必须是唯一的 。
# 9.db_index
如果db_index=True 则代表着为此字段设置索引。
# 10.auto_now
配置上auto_now=True,每次更新数据记录的时候会更新该字段。
# 11.auto_now_add
配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
# 12.choices
用于可以被例举完全的数据
# 13.to
设置要关联的表
# 14.to_field
设置要关联的表的字段
# 15.db_constraint
是否在数据库中创建外键约束,默认为True
'''
外键字段中使用related_name参数可以修改正向查询的字段名
'''
choices示例:
models.py文件:
class Info(models.Model):
username = models.CharField(max_length=255)
password = models.IntegerField()
gender_choies = (
(1,'nan'),
(2,'nv'),
(3,'bian')
)
gender = models.IntegerField(choices=gender_choies)
test.py文件:
res = models.Info.objects.filter(pk=1).first()
print(res.get_gender_display())

事务操作

# MySQL事务四大特性
原子性、一致性、持久性、独立性
# MySQL事务的关键字
开启事务:start transcation
事务回滚:rollback
确认事务:commit
# ORM事务操作
from django.db import transaction
try:
with transaction.atomic(): # with语句结束,事务结束
pass # 事务代码
except Exception:
pass

ORM执行原生SQL

# 方式1
from django.db import connection, connections
cursor = connection.cursor()
cursor = connections['default'].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
cursor.fetchone()
# 方式2
models.UserInfo.objects.extra(
select={'newid':'select count(1) from app01_usertype where id>%s'},
select_params=[1,],
where = ['age>%s'],
params=[18,],
order_by=['-age'],
tables=['app01_usertype']
)

多对多创建方式

# 1.全自动
全自动就是ORM自动创建第三张表,但是没有办法扩展第三张表的字段
示例:authors = models.ManyToManyField(to='Author')
# 2.全手动
第三张表可以完全自定义,扩展性高,但是不能使用外键方法和正反向查询
示例:
class Book(models.Model):
title = 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')
# 3.半自动
可以使用正反向查询,第三张表还可以扩展,但是不能使用add、set、remove、clear这四种方法
示例:
'''
多对多建在任意一方都可以,如果建在Author表,字段顺序互换即可
'''
class Book(models.Model):
title = models.CharField(max_length=32)
authors = models.ManyToManyField(
to='Author',
through='Book2Author', # 指定表
through_fields=('book','author') # 指定字段
)
class Author(models.Model):
name = models.CharField(max_length=32)
class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')

这里是IT小白陆禄绯,欢迎各位大佬的指点!!!

posted @   陆禄绯  阅读(66)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示