Django ORM表查询之F与Q

正反向进阶查询

'''在filter括号内也可以使用正反向查询'''
1.数据对象点正反向概念
2.values点正反向
3.filter括号内使用正反向

eg:
models.Book.objects.filter(publish__pk=1).values('publish_name','publish_addr')

聚合查询

聚合查询关键字:avg,count,summaxmin
'''没有分组之前的聚合函数需要使用关键字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)

分组查询 annotate

'''分组查询的特性是:默认只能够获取分组的字段,其他字段需要使用方法'''
这个特性可以在cmd中取消,具体命令和操作看下图
"""
    1.按照整条数据分组
        models.Book.objects.annotate()  按照一条条书籍记录分组
    2.按照表中某个字段分组()
        models.Book.objects.values('title').annotate()  按照annotate之前values括号中指定的字段分组
"""
# 示例:统计不止一个作者的图书
'''filter在annotate前面则是where 在annotate后面则是having'''
res = models.Book.objects.annotate(author_num=Count('authors__pk')).filter(author_num__gt=1).values('title','author_num')
# print(res)

image

F与Q查询

导入模块 from django.db.models import F/Q
F :能够将表中指定的字段作为关系

'''f查询:查询条件不是自定义的 而是来自表中的其他字段'''
from djano.db.models import f
1.查询库存大于卖出书的书籍
models.Book.objects.filter(storage_num__gt=F('sale_num'))

2.将所有的书籍的价格上涨1000元
 models.Book.objects.update(price=F('price')+1000)
    
3.将所有书籍名称加一个爆款后缀
 from djano.db.models.functions import concat
 from django.db.modles import Value
  models.Book.objects.filter(pk=5).update(title=Concat(F('title'),Value('爆款')))

'''Q:可以改变filter括号内多个条件之间的逻辑运算符 还可以将查询条件的字段改为字符串形式'''
# 将查询条件改为字符串形式
1.先用Q产生一个对象
q_obj=Q()
2.给对象添加查询条件  (可以添加多个 默认为and关系 可以修改为or)
q_obj.children.append('pk',1)
res = models.Book.objects.filter(q_obj)


 eg:动态添加多个查询条件
   res = Q()
   res.connector='OR'  # 指定使用'or'作为查询条件
   res.children.append(('age__contains','18'))   # contain模糊查询 不忽略大小写 icontain 忽略大小写
   res.children.append(('name__contatins','summer'))
   models.user.objects.values('age','name').filter(res) # 查询年龄18或者名字是summer的用户

ORM查询优化(面试会问)

目的是为了减少数据库的使用
多对多四个方法:
#1.only与defer  【单表查询】
	only()
  	数据对象点括号内的字段 不会再走数据库查询
	defer()
    	数据对象点括号内的字段 会再走数据库查询
		
eg:  # only
 res = Book.objects.only('price','title')
 for obj in res:
     print(obj.price)
	 print(obj.title)
	 print(obj.publish)  # 走数据库查询
	 
eg: # defer  【与only刚好相反】
 res = Book.objects.defer('price','title')
 for obj in res:
     print(obj.price)
	 print(obj.title)
	 print(obj.publish)  # 不走数据库查询

# 2.select_related与prefetch_related 【多表查询】
	select_related()
	  # 该方法括号内的参数只能填写一对多和一对一的表 多对多不可用!
       填写外键字段 自动连表 后续无需走数据库查询
	   
res = Book.objects.select_related(publish)
for obj in res:
  print(obj.publish.title)  # 不再走数据库查询 
  
	prefetch_related()
    	填写外键字段 子查询 后续也无需走数据库查询
res = Book.objects.prefetch_related(publish)
for obj in res:
  print(obj.publish.title)  # 不再走数据库查询 
 # 底层就是子查询 其实是走了两条slq的 对比上面的方法多了一条

事务操作

ACID:
    原子性,一致性 隔离性 持久性

 # from django.db import transaction
开启事务:
 trywith transaction.atomic():
       pass                  可以写多条ORM语句
  except Exception as e:
        print(e)
# 用异常捕获检测的话能更好的保障数据的安全性

模型层常见字段

1.AutoField  int自增列,必须填入参数 primary_key=True
2.IntegerField 整数类型
3.CharField 字符串类型 必须提供max_length参数, max_length表示字符长度
 '''Django中的CharField对应的MySQL数据库中的varchar类型 没有设置对应char类型的字段,但是Django允许我们自定义新的字段'''
 
4.DateField 日期字段,日期格式  YYYY-MM-DD

ORM常见字段参数

max_length
verboses_name   # 用于在后台进行显示 类似于中文备注 便于查看
auto_now   #每次更新数据记录的时候会更新该字段
auto_now_add #创建数据记录的时候会把当前时间添加到数据库 除非人为更改 否则一直不变
null
default
max_digits
choice()方法取值   
related_name 关联字段起别名 
unique
models.CASCADE  # 删除数据 关联数据一起删除
# mysql 索引和慢查询优化
foreignkey的on_delete的选择:
1.models.CASCADE 级联删除,用的很少,除非真的删除
2.models.SET_NULL 关联字段可以设为空 null=true
3.models.SET_DEFAULT 关联字段设为默认值 defalut=’‘
4.models.DO_NOTHING 什么都不用做,不用强外键关联
5.models.SET() 放函数内存地址,关联字段删除时,会执行这个函数
# 外键关联的好处与坏处:
  好处:插入修改数据有校验,能够保证数据不会出现错乱,不会出现脏数据
  坏处:有校验速度就会慢,数据量越大速度越慢,可以通过程序控制不加入脏数据
在django中不建立外键关联,也可以使用foreignkey,不需要加to,直接写参数,虽然没有约束但是关系还在
choice
gender_choice = ((1,'男'),(2'女'),(3'未知'))
gender =  models.IntegerField(choices=gender_choice)
print(obj.get_gender_display())  # 直接按照数字对应的中文展示


------------
related_name:反向操作时(基于对象的跨表查询)使用的字段名,用于代替原反向操作时的'表名小写_set'
related_query_name:反向操作时(基于链表的跨表查询)使用的链接前缀,用于替换表名

多对多三种创建方式

# 1.系统自动创建
 models.ManyToManyField(to='')
 优点:第三张表自动创建
 缺点:第三张表扩展性差
 
#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")
优点:可以任意添加想要的属性、
缺点:无法使用正反向查询和多对多四个方法(only和defer,select_related和prefetch_related)

# 3.半自动创建  through
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")
优点:扩展性强,并且支持正反向查询
缺点:无法使用多对多四个方法
posted @   Hsummer  阅读(123)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示