表查询
基于django settings源码实现自己的项目
配置文件的可插拔式设计
dir()
importlib
反射
单表查询
只要是queryset对象 就可以无限制的点击queryset对象的方法
13条
1.all() # 查所有
2.filter() # 根据条件过滤 多个条件之间是and关系
3.get() # 直接获取数据对象 查询条件不存在直接报错
4.first() # 取queryset的第一个数据对象
5.last() # 取queryset的最后一个数据对象
6.exclude() # 除此之外
7.values() # queryset 类似于列表套字典
8.values_list() # queryset 类似于列表套元组
9.count() # 统计数据个数
10.distinct() # 一定要是完全一样的数据才能去重
11.order_by() # 排序 默认是升序 加负号就变成降序
12.reverse() # 反转 排序之后才能反转
13.exists() # 判断queryset是否有值 结果是个布尔值
神奇的双下线的查询
price__gt
price__lt
price__gte
price__lte
price__in=[100,200,300]
price__range=(200,800)
title__contains 包含 模糊匹配
title__icontains 忽略大小写
publish_date__year 只针对年份
publish_date__month 只针对月份
title__startswith
title__endswith
多表查询
前期表准备
图书管理系统
一对多
多对多
一对一
外键字段的增删改查
一对多字段
create(publish_id=1)
create(publish=publish_obj)
update(publish_id=2)
update(publish=publish_obj1)
models.Publish.objects.filter(pk=2).delete()
# orm外键默认是级联更新 级联删除的
多对多字段
# 朝第三张关系表中添加数据
book_obj.authors.add(1)
book_obj.authors.add(1,2,3,4)
book_obj.authors.add(author_obj)
book_obj.authors.add(author_obj,author_obj1,author_obj2)
# 朝第三张表修改数据
book_obj.authors.set((1,))
book_obj.authors.set((1,2,3))
book_obj.authors.set((author_obj,))
book_obj.authors.set((author_obj,author_obj1))
# 朝第三张表删除关系
book_obj.authors.remove(1)
book_obj.authors.remove(1,2,3,4)
book_obj.authors.remove(author_obj)
book_obj.authors.remove(author_obj,author_obj1)
# 朝第三张表清空当前书籍对象所有的记录
book_obj.authors.clear()
跨表查询
正反向的概念:
外键字段在谁那儿 谁就是正向
没有外键字段的 就是反向
口诀:
正向查询按字段
反向查询按表名小写
基于对象 # 子查询
"""
步骤都是先获取一个数据对象
然后利用对象点点点的方式查到锁对应的数据
"""
# 正向
book_obj.publish.name
book_obj.authors.all()
author_obj.author_detail.addr
"""
外键字段所对应的数据 如果是单个 不需要加all
如果是多个 需要加all()
"""
# 反向
publish_obj.book_set.all()
author_obj.book_set.all()
author_detail_obj.author.name
"""
反向查询 数据如果是多个
那么需要 表名小写_set.all()
如果是一个 直接表名小写即可
"""
基于双下划綫 # 连表查询
"""
left join
right join
inner join
union
"""
# 正向
models.Book.objects.filter(title='python').values('publish__name')
# 写外键字段publish之后 就会跨到publish表中 你想要该表的哪个字段对应的数据 就加__字段名获取
models.Book.objecst.filter(pk=1).values('authors__name')
models.Author.objects.filter(name='jason').values('author_detail__addr')
models.Publish.objects.filter(pk=1).values('book__title')
models.authors.objects.filter(pk=1).values('book__title')
models.AuthorDetail.objects.filter(pk=1).values('author__name')
# 反向
models.Publish.objects.filter(book__title='python').values('name')
"""查询书籍id为1 的作者的 手机号"""
models.Book.objects.filter(pk=1).values('authors__author_detail__phone')
聚合查询
聚合函数
from django.db.models import Max,Min,Sum,Count,Avg
分组查询
F与Q查询
orm中常见字段
AutoField(primary_key=True)
CharField(max_length=32) varchar(32)
IntegerField() int
BigIntegerField() long
DateField()
auto_now:每次修改数据的时候 都会更新该字段
auto_now_add:只在创建数据的时候 才会自动将创建时间添加 后续不会再自动修改了
DecimalField()
BooleanField(Field)
- 布尔值类型
该字段在存储数据的时候 你只需要传布尔值即可
对应到数据库中 会变成0/1
TextField(Field)
- 文本类型
存大段文本
EmailField(CharField) varchar(...)
FileField(Field)
- 字符串,路径保存在数据库,文件上传到指定目录
- 参数:
upload_to = "" 上传文件的保存路径
storage = None 存储组件,默认django.core.files.storage.FileSystemStorage
DecimalField(Field)
- 10进制小数
- 参数:
max_digits,小数总长度
decimal_places,小数位长度
自定义char字段
# 自定义char类型字段
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
如果你使用的是django2.X版本 你在建数据库表关系的时候
你需要手动指定两个参数
(你要手动告诉django 级联更新 级联删除 是否建外键约束)
on_delete
db_constraint
!!!!!!!!!!碎片化学习!!!!!!!
查询优化(面试比较喜欢问的)
only与defer
select_related和prefetch_related
django orm中的事务操作
ACID
原子性
一致性
隔离性
持久性
commit
rollback
要么同时成功要么同时失败
from django.db import transaction
with transaction.atomic():
# 在该代码块中所写的orm语句 同属于一个事务
# 缩进出来之后自动结束
聚合查询(aggregate)
from django.db.models import Max,Min,Count,Avg,Sum #查询总和,平均,最大,最小
res = models.Book.objects.aggregate(Sum('price'))
res1 = models.Book.objects.aggregate(Avg('price'))
res2 = models.Book.objects.aggregate(Count('price'))
res3 = models.Book.objects.aggregate(Max('price'))
res4 = models.Book.objects.aggregate(Min('price'))
res5 = models.Book.objects.aggregate(Max('price'),Min('price'),Count('pk'),Avg('price'),Sum('price')) #也可以放在一个里面写
分组查询 (annotate)
1.统计每一本书的作者个数
from django.db.models import Max, Min, Count, Avg, Sum
res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title')
#book表根据authors分组求和,author_num是取的别名,values是控制台打印的值
2.统计每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(mmp = Min('book__price')).values('name','mmp')
3.统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)
4.查询每个作者出的书的总价格
res = models.Author.objects.annotate(sp=Sum('book__price')).values('name','sp')
F查询与Q查询
F查询的本质就是从数据库中获取某个字段的值,之前查询等号后面的条件都是我们人为输入的,现在变成了需要从数据库中获取数据放在等号后面
查询库存量大于卖出量的书籍
from django.db.models import F
res = models.Book.objects.filter(kucun__gt=F('maichu')) #kucun和maichu都是Book表的字段
将书籍库存数全部增加1000
models.Book.objects.update(kucun=F('kucun')+1000)
把所有书名后面加上'新款'
from django.db.models.functions import Concat
from django.db.models import Value
ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))
models.Book.objects.update(title = F('title')+'新款') # 不能这么写
Q查询 (filter里面条件都是与,Q支持与或非)
查询书籍名称是三国演义或者价格是444
from django.db.models import Q
res = models.Book.objects.filter(title='三国演义',price=444.44) # filter只支持and关系
res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444)) # 如果用逗号 那么还是and关系
res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444)) #或者关系
res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444)) #查询除了title是三国演义,或者价格是444的书籍
Q的高级用法
from django.db.models import Q
q = Q()
q.connector = 'or' # 修改查询条件的关系 默认是and
q.children.append(('title__contains','三国演义')) # 往列表中添加筛选条件
q.children.append(('price__gt',444)) # 往列表中添加筛选条件
res = models.Book.objects.filter(q) # filter支持你直接传q对象 但是默认还是and关系
print(res)
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Django聚合查询、分组查询、F与Q查询 - Python技术站