当前位置: 首页 > news >正文

Django ORM查询技巧全解析

一、单表查询:

基础查询:

  1. 查询所有数据(all ())

    • 用法:User.objects.all()
    • 说明:返回表中所有记录,结果为 QuerySet 集合
    • 模板中使用:{% for user in userlist %}{{ user.username }}{% endfor %}
  2. 精确查询单个对象(get ())

    • 用法:User.objects.get(username="乔巴43324")
    • 说明:返回满足条件的唯一对象
    • 注意:若查询结果不存在或多于一个,会抛出异常
    • 模板中使用:直接访问属性{{ user.username }}
  3. 条件筛选查询(filter ())

    • 用法:User.objects.filter(username="路飞123")
    • 说明:返回满足条件的所有记录,结果为 QuerySet 集合
    • 特点:无匹配结果时返回空集合,不会报错
    • 模板中使用:{% for user in userlist %}{{ user.username }}{% endfor %}
  4. 查询指定字段(values ())

    • 用法:User.objects.all().values("id","username")
    • 说明:返回包含指定字段的字典集合,格式为{key:value, key:value}
    • 适用场景:前台只需要部分字段数据时
  5. 查询指定字段值(values_list ())

    • 用法:User.objects.all().values_list("id", "username")
    • 说明:返回包含指定字段值的元组集合,如[(1, '路飞123'), (2, '乔巴')]
    • 适用场景:只需要字段值而不需要对象属性时
  6. 排除条件查询(exclude ())

    • 用法:User.objects.exclude(id=2)
    • 说明:返回除满足条件之外的所有记录
  7. 排序查询(order_by ())

    • 基本用法:User.objects.order_by("sal")(默认升序)
    • 降序查询:User.objects.order_by("-id")(字段前加负号)
    • 多字段排序:User.objects.order_by("sal", "-id")(先按 sal 升序,相同则按 id 降序)
  8. 反转排序(reverse ())

    • 用法:User.objects.order_by("-id").reverse()
    • 说明:对已排序的结果进行反转,需先使用 order_by ()
  9. 统计记录数(count ())

    • 用法:User.objects.all().count()
    • 说明:返回查询结果的记录总数
  10. 获取首尾记录(first ()/last ())

    • 用法:User.objects.all().last() 或 User.objects.all().first()
    • 说明:返回查询结果中的第一条或最后一条记录,结果为对象
  11. 判断记录是否存在(exists ())

    • 用法:User.objects.filter(id=2).exists()
    • 说明:判断查询结果是否存在,返回布尔值(True/False)

组合示例

User.objects.filter(status=1).order_by("-create_time").values("id", "name")

下划线查询:

  1. 比较查询

    • 属性__gt=值:大于(>),如 id__gt=1 表示 id > 1
    • 属性__gte=值:大于等于(>=),如 age__gte=18 表示 age >= 18
    • 属性__lt=值:小于(<),如 price__lt=100 表示 price < 100
    • 属性__lte=值:小于等于(<=),如 score__lte=60 表示 score <= 60
  2. 范围查询

    • 属性__range=[start, end]:在指定范围内(包含边界),如 id__range=[1,3] 等价于 id >= 1 and id <= 3
  3. 成员查询

    • 属性__in=[值1, 值2, ...]:匹配列表中的任意值,如 id__in=[1,3,5] 等价于 id=1 or id=3 or id=5
  4. 模糊查询

    • 属性__contains=值:包含指定字符(区分英文大小写),如 username__contains="路" 等价于 like '%路%'
    • 属性__icontains=值:包含指定字符(不区分英文大小写),如 username__icontains="lu" 会匹配 "LU"、"Lu" 等
    • 属性__startswith=值:以指定字符开头,如 name__startswith="张" 等价于 like '张%'
    • 属性__endswith=值:以指定字符结尾,如 email__endswith="qq.com" 等价于 like '%qq.com'
  5. 多条件组合
    可以将多个下划线查询条件组合使用,实现复杂过滤:

    # 查询 id>1 且 id<=3 的用户
    User.objects.filter(id__gt=1, id__lte=3)

二,多表查询

一对多

1、基础概念

  • 一对多关系:一个出版社(一方)可关联多本图书(多方),图书通过外键(如press = models.ForeignKey(Press, ...))关联到出版社。
  • 查询方向:分为 “从多方查一方”“从一方查多方”“反向查询” 三类。

2、从多方(Book)查询一方(Press)

即通过图书查询其所属的出版社,利用外键字段直接访问关联的一方对象。

.直接获取关联的一方对象
# 获取id=2的图书,再访问其关联的出版社
book = Book.objects.get(id=2)
print(book.press)  # 输出该图书对应的Press对象
print(book.press.pressname)  # 访问出版社的字段(如出版社名称)
  • 原理:通过多方模型的外键字段(press)直接获取关联的一方实例。

3、从一方(Press)查询多方(Book)

即通过出版社查询其所有关联的图书,有两种常用方式:

 3.1通过外键 ID 查询(直接条件过滤)
# 查询出版社id=1对应的所有图书(直接使用外键的id字段)
booklist = Book.objects.filter(press_id=1)
  • 说明:press_id是外键在数据库中的实际字段名(默认外键字段名_id),直接通过 ID 过滤多方数据。
3.2 跨表联查(通过一方字段过滤)

利用外键字段__一方字段的语法实现跨表查询,生成一条联表 SQL。

# 查询名称包含“清华”的出版社对应的所有图书
booklist = Book.objects.filter(press__pressname__contains="清华")
  • 语法:外键字段(press)__一方字段(pressname),支持嵌套(如__contains模糊查询)。
  • 优势:仅执行一次 SQL 查询,效率更高。
3.3 先查一方对象,再通过 ID 关联(多 SQL 查询)
# 先查询出版社对象,再通过其ID过滤图书(生成两条SQL)
press = Press.objects.get(pressname="清华大学出版社")
booklist = Book.objects.filter(press_id=press.id)
  • 说明:分两步查询,先获取一方实例,再用其 ID 作为条件查询多方,适用于需要先处理一方对象的场景。

四、反向查询(从一方主动查询多方)

一方模型本身不直接存储外键,需通过 “反向关联” 语法查询多方数据,有两种方式:

1. 默认反向关联(多方类名小写_set

Django 自动生成的反向关联属性,格式为多方模型类名小写_set

# 查询“清华大学出版社”关联的所有图书
press = Press.objects.get(pressname="清华大学出版社")
booklist = press.book_set.all()  # book_set是自动生成的反向关联属性
  • 说明:book_set本质是一个管理器(Manager),支持all()filter()等查询方法。
2. 自定义反向关联(related_name

在定义外键时通过related_name指定反向关联名称,替代默认的book_set

# 定义外键时指定related_name
class Book(models.Model):press = models.ForeignKey(Press, on_delete=models.CASCADE, related_name="books")  # 自定义反向名称为books# 使用自定义名称查询
press = Press.objects.get(pressname="清华大学出版社")
booklist = press.books.all()  # 直接使用related_name(books)访问
  • 优势:更直观,推荐使用。

五、跨表查询指定字段(values ())

通过values()指定多方和一方的字段,返回包含跨表字段的字典。

# 查询所有图书的名称及其对应出版社的名称
booklist = Book.objects.all().values("bookname", "press__pressname")
# 结果示例:[{'bookname': '鹿鼎记', 'press__pressname': '人民文学出版社'}, ...]
  • 语法:values(多方字段, 外键字段__一方字段),适合只需要部分字段的场景。

六、通过多方字段反向查询一方

即根据多方的条件查询对应的一方(如 “查询《鹿鼎记》所属的出版社”)。

# 查询图书名称为“鹿鼎记”的图书对应的出版社
press = Press.objects.get(books__bookname="鹿鼎记")  # books是related_name
  • 原理:利用反向关联名称(books)+ 多方字段(bookname)过滤一方数据。

总结

查询场景核心语法 / 方法示例
多方查一方多方对象。外键字段book.press.pressname
一方查多方(ID 过滤)Book.objects.filter(press_id=一方ID)Book.objects.filter(press_id=1)
一方查多方(跨表联查)Book.objects.filter(外键__一方字段=条件)filter(press__pressname__contains="清华")
反向查询(默认)一方对象。多方类名小写_set.all ()press.book_set.all()
反向查询(自定义)一方对象.related_name.all ()press.books.all()(需定义 related_name)
跨表指定字段values(多方字段, 外键__一方字段)values("bookname", "press__pres

三、聚合查询

用于对数据进行统计计算(如求和、平均值等),核心是对一组数据进行汇总分析。

1. 核心特点
  • 作用:对查询集(QuerySet)进行统计计算,返回汇总结果。
  • 常用函数:SumAvgMaxMinCount(需从django.db.models导入)。
  • 常用方法:
    • aggregate():返回整体统计结果(字典)。
    • annotate():为每个对象添加聚合字段(分组统计)。
2. 示例
from django.db.models import Sum, Avg, Count
from .models import Product# 1. 整体统计(aggregate)
# 计算所有商品的平均价格、总库存
result = Product.objects.aggregate(avg_price=Avg('price'),total_stock=Sum('stock')
)
# 结果:{'avg_price': 89.5, 'total_stock': 500}# 2. 分组统计(annotate)
# 统计每个分类下的商品数量
from .models import Category
categories = Category.objects.annotate(product_count=Count('product')  # product是Category与Product的关联名称
)
for c in categories:print(f"分类{c.name}有{c.product_count}个商品")

四、F 表达式

用于引用模型字段的值,实现字段间的直接计算或比较,避免 Python 层面的二次处理。

1. 核心特点
  • 作用:在数据库层面操作字段值,无需将数据加载到内存。
  • 适用场景:字段间比较、基于字段值的更新、计算等。
  • 导入:from django.db.models import F
2. 示例
from django.db.models import F
from .models import Product# 1. 字段间比较查询
# 查询库存大于销量的商品(stock > sales)
products = Product.objects.filter(stock__gt=F('sales'))# 2. 基于字段值的更新
# 所有商品价格上涨10%(price = price * 1.1)
Product.objects.update(price=F('price') * 1.1)# 3. 字段计算作为新值
# 查询时添加“库存余量”字段(stock - sales)
products = Product.objects.annotate(remaining=F('stock') - F('sales')
).values('name', 'remaining')

五、Q 表达式

用于构建复杂的查询条件,支持逻辑运算符(与、或、非)组合多个查询条件。

1. 核心特点
  • 作用:处理多条件的逻辑组合(如OR关系),弥补filter()默认AND逻辑的不足。
  • 运算符:
    • Q(a) | Q(b):逻辑或(a 或 b)
    • Q(a) & Q(b):逻辑与(a 且 b,等价于filter(a, b)
    • ~Q(a):逻辑非(非 a)
  • 导入:from django.db.models import Q
2. 示例
from django.db.models import Q
from .models import Product# 1. 逻辑或(OR)查询
# 查询价格低于50元 或 库存大于100的商品
products = Product.objects.filter(Q(price__lt=50) | Q(stock__gt=100)
)# 2. 组合逻辑(与+或)
# 查询(价格>100且销量>50) 或 分类为"数码"的商品
products = Product.objects.filter(Q(price__gt=100) & Q(sales__gt=50) | Q(category__name="数码")
)# 3. 逻辑非(NOT)
# 查询不属"数码"分类的商品
products = Product.objects.filter(~Q(category__name="数码"))

六、三者的结合使用

聚合查询、F、Q 表达式可以灵活组合,解决更复杂的需求。

1. 聚合 + F 表达式
# 计算每个商品的“总价”(price * stock),并统计所有商品的总价之和
from django.db.models import Sum, Ftotal_value = Product.objects.aggregate(total=Sum(F('price') * F('stock'))  # 先计算单商品总价,再求和
)
# 结果:{'total': 25600.0}(所有商品库存总价值)
2. 聚合 + Q 表达式
# 统计“价格>100或销量>50”的商品总数
from django.db.models import Count, Qcount = Product.objects.filter(Q(price__gt=100) | Q(sales__gt=50)
).aggregate(total=Count('id'))
# 结果:{'total': 30}
3. 三者结合
# 统计每个分类中“库存>销量”的商品数量
categories = Category.objects.annotate(valid_count=Count('product', filter=Q(product__stock__gt=F('product__sales'))  # 过滤条件:库存>销量)
)

七、核心区别与应用场景

工具核心作用典型场景
聚合查询数据统计(求和、平均值等)计算总数、分组统计、跨表汇总
F 表达式字段间操作(比较、计算)字段比较、基于原字段更新、动态计算字段值
Q 表达式组合复杂查询条件(逻辑运算)实现 OR、NOT 逻辑,多条件灵活组合

http://www.lryc.cn/news/617169.html

相关文章:

  • 41.【.NET8 实战--孢子记账--从单体到微服务--转向微服务】--扩展功能--集成网关--网关集成Swagger
  • Spring MVC 注解参数接收详解:@RequestBody、@PathVariable 等区别与使用场景
  • kafka 中的Broker 是什么?它在集群中起什么作用?
  • [Oracle] UNPIVOT 列转行
  • CodeBuddy IDE完全食用手册:从安装到生产力爆发的技术流解剖
  • 视频前处理技术全解析:从基础到前沿
  • 【安全发布】微软2025年07月漏洞通告
  • AI大模型:(二)5.1 文生视频(Text-to-Video)模型发展史
  • 从ELF到进程间通信:剖析Linux程序的加载与交互机制
  • 音视频学习(五十三):音频重采样
  • 动态创建可变对象:Python类工厂函数深度解析
  • Vue3从入门到精通:3.1 性能优化策略深度解析
  • Unity跨平台性能优化全攻略:PC与安卓端深度优化指南 - CPU、GPU、内存优化 实战案例C#
  • docker集群
  • 在Linux中部署tomcat
  • MyBatis高级特性与性能优化:从入门到精通的实战指南
  • NEON性能优化总结
  • EXISTS 替代 IN 的性能优化技巧
  • Unity大型场景性能优化全攻略:PC与安卓端深度实践 - 场景管理、渲染优化、资源调度 C#
  • C# 异步编程(BeginInvoke和EndInvoke)
  • openEuler、 CentOS、Ubuntu等 Linux 系统中,Docker 常用命令总结
  • Selenium经典面试题 - 多窗口切换解决方案
  • 深入解析游戏引擎(OGRE引擎)通用属性系统:基于Any类的类型安全动态属性设计
  • 如何在 Ubuntu 24.04 LTS Linux 上安装和使用 Flatpak
  • 游戏引擎(Unreal Engine、Unity、Godot等)大对比:选择最适合你的工具
  • [Ubuntu] VNC连接Linux云服务器 | 实现GNOME图形化
  • 从零开始的云计算生活——项目实战容器化
  • Ubuntu 22.04 离线环境下 Python 包与 FFmpeg 安装全攻略​
  • Python 爬虫:Selenium 自动化控制(Headless 模式 / 无痕浏览)
  • 使用Windbg分析多线程死锁项目实战问题分享