from django.db import modelsclass Book(models.Model):title = models.CharField(max_length=200)  # 书名author = models.CharField(max_length=100)  # 作者publish_date = models.DateField()  # 出版日期price = models.DecimalField(max_digits=10, decimal_places=2)  # 价格stock = models.IntegerField(default=0)  # 库存,默认0def __str__(self):return self.title

创建对象

save

# 1. 创建实例
book = Book(title="Django 入门",author="张三",publish_date=date(2023, 1, 1),price=59.99,stock=100
)# 2. 保存到数据库
book.save()  # 执行 INSERT 语句

create

直接创建并保存,返回创建的实例:

book = Book.objects.create(title="Python 编程",author="李四",publish_date=date(2022, 5, 10),price=49.99,stock=50
)

bulk_create

高效创建多条记录(仅执行一次 SQL):

books = [Book(title="Java 实战", author="王五", publish_date=date(2021, 3, 15), price=69.99, stock=30),Book(title="JavaScript 指南", author="赵六", publish_date=date(2023, 2, 20), price=55.50, stock=40)
]Book.objects.bulk_create(books)  # 批量插入

get_or_create

查询记录,若不存在则创建:

book, created = Book.objects.get_or_create(title="Django 入门",  # 查询条件defaults={  # 若不存在,新增时的其他字段"author": "张三","publish_date": date(2023, 1, 1),"price": 59.99,"stock": 100}
)
# created 是布尔值:True 表示新建,False 表示查询到已有记录

查询

基础查询

all

查询所有记录

all_books = Book.objects.all()

get

查询单条记录(必须匹配一条,否则报错)

book = Book.objects.get(id=1)  # 通过 ID 查询
book = Book.objects.get(title="Django 入门")  # 通过字段查询

filter

查询符合条件的多条记录

# 价格大于 50 的书
expensive_books = Book.objects.filter(price__gt=50)# 作者是张三且库存大于 0 的书
zhang_books = Book.objects.filter(author="张三", stock__gt=0)

exclude

# 排除价格小于等于 50 的书(即查询价格 >50 的书)
cheap_books = Book.objects.exclude(price__lte=50)

高级查询

条件表达式

  • __gt:大于(price__gt=50 → 价格 >50)
  • __lt:小于
  • __gte:大于等于
  • __lte:小于等于
  • __contains:包含(模糊查询,区分大小写)
  • __icontains:包含(不区分大小写)
  • __in:在列表中(author__in=[“张三”, “李四”])
  • __range:在范围内(publish_date__range=(start_date, end_date))
  • __isnull:是否为 null(author__isnull=True)
# 书名包含 "Django" 的书(不区分大小写)
django_books = Book.objects.filter(title__icontains="django")# 2023 年出版的书
from datetime import date
start = date(2023, 1, 1)
end = date(2023, 12, 31)
books_2023 = Book.objects.filter(publish_date__range=(start, end))

F查询

F() 表达式用于直接引用模型字段的值,允许在数据库层面进行字段间的比较或运算,而无需先将数据加载到 Python 内存中。

# 示例:查询库存大于销量的书籍(假设有 sales 字段)
books = Book.objects.filter(stock__gt=F('sales'))# 解释:直接在数据库中比较 stock 和 sales 字段,避免了 Python 层面的计算

字段运算

# 示例1:所有书籍涨价 10%
Book.objects.all().update(price=F('price') * 1.1)# 示例2:某本书库存减少 5
book = Book.objects.get(id=1)
book.stock = F('stock') - 5
book.save()# 注意:保存后需要刷新实例才能看到最新值(因为 F() 是数据库层面的操作)
book.refresh_from_db()  # 从数据库重新加载数据

跨关系使用

class Author(models.Model):name = models.CharField(max_length=100)age = models.IntegerField()class Book(models.Model):title = models.CharField(max_length=200)author = models.ForeignKey(Author, on_delete=models.CASCADE)publish_year = models.IntegerField()# 示例:查询出版年份大于作者年龄的书籍(假设作者年龄与出版年份有逻辑关联)
books = Book.objects.filter(publish_year__gt=F('author__age'))

Q 查询

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

|

# 示例:查询价格大于 100 元 或 作者是 "张三" 的书籍
books = Book.objects.filter(Q(price__gt=100) | Q(author="张三")  # | 表示逻辑或
)

&

# 示例:查询价格大于 100 元 且 作者是 "张三" 的书籍
# 等价于 filter(price__gt=100, author="张三"),但 Q() 更灵活
books = Book.objects.filter(Q(price__gt=100) & Q(author="张三")  # & 表示逻辑与
)

~

# 示例:查询作者不是 "张三" 的书籍
books = Book.objects.filter(~Q(author="张三")  # ~ 表示逻辑非
)

嵌套使用

# 示例:查询(价格 >100 且 2023 年出版) 或 (作者是张三且库存 >0)的书籍
books = Book.objects.filter(Q(price__gt=100, publish_year=2023) | Q(author="张三") & Q(stock__gt=0)
)
# 等价于 Q(author="张三") & Q(price__gt=100)
books = Book.objects.filter(author="张三", Q(price__gt=100))

F () 与 Q () 结合使用

# 示例:查询(库存 > 销量 且 价格 > 50) 或 (作者是张三)的书籍
books = Book.objects.filter((Q(stock__gt=F('sales')) & Q(price__gt=50)) | Q(author="张三")
)

排序与限制

order_by

# 按价格升序(默认)
books_by_price = Book.objects.order_by("price")# 按价格降序(加负号)
books_by_price_desc = Book.objects.order_by("-price")

first / last

first_book = Book.objects.first()
last_book = Book.objects.last()

reverse

反转 QuerySet 顺序(需先排序)

reversed_books = Book.objects.order_by("price").reverse()  # 等效于 order_by("-price")

切片

# 取前 10 条
top10_books = Book.objects.all()[:10]# 分页:取第 11-20 条
page2_books = Book.objects.all()[10:20]

分组聚合

分组聚合(Group By + Aggregation)是处理统计分析类需求的强大工具,常用于计算分组数据的总和、平均值、数量等。

from django.db.models import Avg, Sum, Count# 平均价格
avg_price = Book.objects.aggregate(Avg("price"))  # {'price__avg': 58.33}# 总库存
total_stock = Book.objects.aggregate(Sum("stock"))  # {'stock__sum': 220}# 按作者分组,统计每个作者的书籍数量
author_book_count = Book.objects.values("author").annotate(Count("id"))
# 结果:[{'author': '张三', 'id__count': 1}, {'author': '李四', 'id__count': 1}, ...]

去重计数(distinct=True)

# 统计每个作者的不同出版社数量(假设有 publisher 字段)
result = Book.objects.values('author').annotate(publisher_count=Count('publisher', distinct=True)
)

对 DateTimeField 字段,可按年、月、日等粒度分组(需结合 Trunc 函数):

from django.db.models.functions import TruncYear, TruncMonth# 按出版年份分组,统计每年出版的书籍数量
result = Book.objects.annotate(publish_year=TruncYear('publish_date')  # 提取年份
).values('publish_year').annotate(book_count=Count('id')
)# 按出版月份分组(如 2023-01, 2023-02)
result = Book.objects.annotate(publish_month=TruncMonth('publish_date')  # 提取年月
).values('publish_month').annotate(book_count=Count('id')
)

多个聚合值

# 按作者分组:统计书籍数量、平均价格、总库存
result = Book.objects.values('author').annotate(book_count=Count('id'),avg_price=Avg('price'),total_stock=Sum('stock')
)

多字段分组 + 过滤

# 按作者和出版年份分组,统计每组书籍数量
result = Book.objects.values('author', 'publish_year').annotate(book_count=Count('id')
).order_by('author', 'publish_year')  # 按分组字段排序# 结果格式:
# [
#   {'author': '张三', 'publish_year': 2023, 'book_count': 2},
#   {'author': '张三', 'publish_year': 2022, 'book_count': 1},
#   ...
# ]

子查询与聚合结合

# 子查询:统计每个作者的书籍数量
author_book_count = Book.objects.filter(author=OuterRef('pk')
).annotate(count=Count('id')
).values('count')# 主查询:查询所有作者,并附加其书籍数量
authors = Author.objects.annotate(book_count=Subquery(author_book_count[:1])  # 取子查询结果的第一条
)

分组后过滤(filter() 与 having 区别)

  • filter():在分组之前过滤数据(类似 SQL 的 WHERE)。
  • annotate() 后再 filter():在分组之后过滤(类似 SQL 的 HAVING)。
# 示例1:先过滤(2020年以后出版的书),再分组统计
result1 = Book.objects.filter(publish_year__gt=2020).values('author').annotate(book_count=Count('id')
)# 示例2:先分组,再过滤分组结果(只保留书籍数量 > 2 的作者)
result2 = Book.objects.values('author').annotate(book_count=Count('id')
).filter(book_count__gt=2)  # 此处 filter 等效于 HAVING book_count > 2

对关联模型(如外键、多对多)进行分组聚合时,需通过双下划线(__)关联字段。

class Author(models.Model):name = models.CharField(max_length=100)country = models.CharField(max_length=50)  # 作者所属国家class Book(models.Model):title = models.CharField(max_length=200)author = models.ForeignKey(Author, on_delete=models.CASCADE)  # 外键关联作者price = models.DecimalField(max_digits=10, decimal_places=2)
# 按作者的国家分组,统计每个国家的书籍总数和平均价格:
from django.db.models import Count, Avgresult = Book.objects.values('author__country').annotate(total_books=Count('id'),avg_book_price=Avg('price')
)# 结果格式:
# [
#   {'author__country': '中国', 'total_books': 10, 'avg_book_price': 55.5},
#   {'author__country': '美国', 'total_books': 8, 'avg_book_price': 62.3},
#   ...
# ]
常用聚合函数
  • Count
  • Sum
  • Avg
  • Max
  • Min
  • StdDev: 标准差(仅部分数据库支持)
  • Variance: 方差(仅部分数据库支持)

values

返回字典列表(键为字段名)。

# 获取所有书籍的标题和作者
book_data = Book.objects.values('title', 'author__name')
# 结果:[{'title': 'Django 入门', 'author__name': '张三'}, ...]

values_list

# 获取所有书籍标题(扁平列表)
titles = Book.objects.values_list('title', flat=True)
# 结果:['Django 入门', 'Python 编程', ...]

only

仅加载指定字段(其他字段访问会触发新查询)。

# 只加载书名和作者(适合列表展示等场景)
books = Book.objects.only('title', 'author__name')

defer

延迟加载指定字段(与 only 相反)。

# 不加载大文本字段 content(适合不需要展示详情的场景)
books = Book.objects.defer('content')

select_related

select_related:用于外键 / 一对一关系,通过 JOIN 一次性加载关联对象(适用于 “单对象” 关联)。

# 普通查询(会产生 N+1 条 SQL:1 条查书籍,N 条查对应作者)
books = Book.objects.all()
for book in books:print(book.author.name)  # 每次访问 author 都会触发新查询# 优化后(仅 1 条 SQL,通过 JOIN 加载书籍和关联的作者)
books = Book.objects.select_related('author').all()
for book in books:print(book.author.name)  # 无额外查询

prefetch_related

用于多对多 / 反向外键关系,通过单独查询关联对象再在 Python 中关联(适用于 “多对象” 关联)。

# 优化多对多查询(书籍与标签)
books = Book.objects.prefetch_related('tags').all()
for book in books:print([tag.name for tag in book.tags.all()])  # 无额外查询
# 加载书籍、作者及其所有作品
books = Book.objects.select_related('author').prefetch_related('author__books').all()

原始 SQL 查询

raw

raw(sql, params=None):执行原始 SQL 并返回模型实例

books = Book.objects.raw("SELECT * FROM myapp_book WHERE price > %s", [50])

extra()

附加 SQL 片段(不推荐,建议用 annotate 或 F/Q)

books = Book.objects.extra(where=["price > 50"])

QuerySet 基本特性

QuerySet 是 Django ORM 中用于与数据库交互的核心对象,它代表数据库中一组记录的集合,支持链式操作和延迟执行。

延迟执行(Lazy Evaluation)

QuerySet 不会立即执行数据库查询,直到真正需要使用数据时才会触发 SQL 执行。这是 QuerySet 最核心的特性之一。

# 定义 QuerySet(未执行查询)
books = Book.objects.filter(author="张三")# 以下操作会触发 SQL 执行:
print(books)  # 打印时
for book in books:  # 迭代时pass
list(books)  # 转换为列表时
if books:  # 判断布尔值时

可链式调用

# 链式调用:价格大于 50 且 2023 年出版的书,按价格降序
books = Book.objects.filter(price__gt=50).filter(publish_year=2023).order_by("-price")

不可变对象

QuerySet 是不可变的,每次链式调用都会返回一个新的 QuerySet,原 QuerySet 不会被修改:

qs1 = Book.objects.filter(author="张三")
qs2 = qs1.filter(price__gt=50)  # qs1 不变,qs2 是新的 QuerySet
复制 QuerySet

由于 QuerySet 是不可变的,可通过 all() 复制:

qs1 = Book.objects.filter(author="张三")
qs2 = qs1.all()  # 复制 qs1,后续操作不影响 qs1

QuerySet 与其他对象的区别

在这里插入图片描述

更新数据

save

单个实例更新

# 1. 查询实例
book = Book.objects.get(id=1)# 2. 修改字段
book.price = 65.99  # 涨价
book.stock -= 1  # 库存减1# 3. 保存到数据库
book.save()  # 执行 UPDATE 语句

update

# 所有张三的书涨价 10%
Book.objects.filter(author="张三").update(price=F("price") * 1.1)
# 注意:F() 用于引用字段本身,避免先查询再计算的竞态问题

bulk_update

# 1. 查询需要更新的实例
books = Book.objects.filter(author="张三")# 2. 修改实例字段
for book in books:book.stock += 5  # 库存各加5# 3. 批量更新(指定需要更新的字段)
Book.objects.bulk_update(books, ["stock"])

条件更新与 Case/When

from django.db.models import Case, When, IntegerField# 对不同书籍设置不同库存
Book.objects.update(stock=Case(When(title__icontains="Django", then=100),  # Django 相关书籍库存设为 100When(author="张三", then=50),  # 张三的书库存设为 50default=0,  # 其他默认 0output_field=IntegerField())
)

删除

book = Book.objects.get(id=1)
book.delete()  # 执行 DELETE 语句# 删除所有库存为 0 的书
Book.objects.filter(stock=0).delete()
  • 删除操作不可逆,谨慎使用。
  • 若模型设置了 on_delete 关联关系(如外键),删除时会触发对应的级联行为(如 CASCADE 级联删除)。

其他操作

iterator

适合大数据量,减少内存占用(一次加载一批)

# 处理 100 万条记录,每次加载 1000 条
for book in Book.objects.iterator(chunk_size=1000):process(book)

refresh_from_db

刷新实例(从数据库重新加载)

book = Book.objects.get(id=1)
# 其他操作可能修改了数据库中的记录...
book.refresh_from_db()  # 从数据库重新加载最新数据

count

# 总书籍数量
total = Book.objects.count()# 张三的书籍数量
zhang_count = Book.objects.filter(author="张三").count()

exists

# 判断是否有价格大于 100 的书
has_expensive = Book.objects.filter(price__gt=100).exists()  # 返回布尔值

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/91493.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/91493.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/91493.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【绘制图像轮廓】——图像预处理(OpenCV)

目录 1 什么是轮廓 2 寻找轮廓 2.1 mode参数 2.2 method参数 3 绘制轮廓 1 什么是轮廓 轮廓是一系列相连的点组成的曲线,代表了物体的基本外形。轮廓是连续的,边缘不一定连续。轮廓是一个闭合的、封闭的形状。 轮廓的作用: 形状分析 目…

嵌入式 Linux 深度解析:架构、原理与工程实践(增强版)

嵌入式 Linux 深度解析:架构、原理与工程实践(增强版) 目录嵌入式 Linux 深度解析:架构、原理与工程实践(增强版)第一章 嵌入式 Linux 基础概念1.1 定义与核心特征1.2 典型架构栈深度解析第二章 Linux 文件…

xcode swift项目运行、连接真机运行报错,引入文件夹失败

最近乱七八糟解决了很多报错,看着记录点吧 xcode版本:16 failed to emit precompiled header ‘/Users/yuqing/Library/Developer/Xcode/DerivedData/cloudspace-ios-ejldldcfhouqnretchuzoewmsqkg/Build/Intermediates.noindex/PrecompiledHeaders/spic…

[python][selenium] Web UI自动化8种页面元素定位方式

测试工程师必备!Selenium自动化测试全攻略 | 手写POM框架数据驱动,轻松搞定UI自动化!简单的加个前置知识: 第一:webdriver.Chrome()这句话,通过WebDriver的构造方法,拿到浏览器驱动的对象&…

丝杆支撑座在电子装配中的关键作用

丝杆支撑座是电子装配过程中不可或缺的组件,主要用于支撑和固定丝杆,确保其稳定性和精度。在高速、高精度装配场景中,丝杆支撑座的作用尤为突出。稳定性与精度保障:丝杆支撑座采用高品质钢材制作,具有高刚性和高强度&a…

微信小程序页面间通信的实现方式

微信小程序中页面间的通信是指不同页面之间的数据传递、状态同步或交互操作,常见于多页面协作场景。根据通信方向和场景不同,主要有以下几种实现方式:一、基于页面跳转的参数传递1. 正向传递(A页面到B页面)通过URL参数…

uniapp开发微信小程序(新旧版本对比:授权手机号登录、授权头像和昵称)

目录标题授权手机号新旧版本核心差异对比强制使用新版的情况代码实现方案特殊处理逻辑企业账号要求最佳实践建议授权头像和昵称新旧版本核心差异对比强制使用新版的情况代码实现方案最佳实践建议注意事项授权手机号 新旧版本核心差异对比 触发方式 旧版(2023年前&…

Java函数式编程之【Stream终止操作】【下】【三】【收集操作collect()与分组分区】【下游收集器】

分组收集器groupingBy():groupingBy()收集器用于按条件对元素象进行分组,并将结果存储在Map实例中。其作用与数据库的SQL语句的group by的用法有异曲同工之妙。 分区收集器partitioningBy():partitioningBy()可以看作是分组groupingBy()的特殊…

python设计模式-工厂模式

工厂模式的核心思想:封装对象创建过程、解耦对象使用与创建 。示例代码:from enum import Enum# 基类:人类 class Person:species Homo sapiensdef __init__(self, name):self.name namedef __str__(self):return f"{self.__class__._…

Rust:anyhow::Result 与其他 Result 类型转换

当函数返回的不是 anyhow::Result 而是其他 Result 类型时(如 std::io::Result、serde_json::Result 或自定义 Result),可通过以下方法统一处理错误类型,确保与 anyhow 兼容或实现错误传播:🛠️ 一、错误类…

PLC-梯形图编程

1.位运算,比较 如&#xff1a;>,<,, 2.定时器 生成脉冲TP&#xff0c;常开触点闭合触发&#xff0c;赋值10秒时长&#xff0c;PT配置参数&#xff0c;ET运行时已PT计时 接通延时TON&#xff0c;常开触点闭合触发&#xff0c;延时10秒后赋值 关断延时TOF&#xff0c;常开触…

LLM学习笔记5——InstructGPT

系列文章目录 参考文献 参考文献 参考文献 参考视频 文章目录系列文章目录前言目前大模型不同的技术流派与框架路线&#xff1a;1. ​​BERT&#xff1a;Encoder-only架构​​​​1&#xff09; 架构特点​​​​2&#xff09; 训练目标​​3&#xff09; ​​​​应用场景2. …

热能小车cad【12张】三维图+设计说明书

摘要 无碳小车来自全国大学生工程能力训练大赛题目&#xff0c;根据“节能减排&#xff0c;绿色出行”的环保理念&#xff0c;提出了一种基于热力驱动的具有方向自动控制的无碳小车。 本文设计的无碳小车主要是将热能转化成机械能&#xff0c;用来驱动小车前进的装置&#xff0…

云原生 DevOps 实战之Jenkins+Gitee+Harbor+Kubernetes 构建自动化部署体系

技术背景​ 在云原生生态中&#xff0c;工具链的选择直接决定 CI/CD 流水线的效率与稳定性。本次方案的工具组合并非偶然&#xff0c;而是基于各组件的核心优势与生态适配性&#xff1a;​ 代码管理层&#xff1a;Gitee 作为国内主流的代码托管平台&#xff0c;支持 Git 分布…

二建机电工程专业都考哪些知识点?

二建机电工程专业需要考《建设工程施工管理》《建设工程法规及相关知识》和《机电工程管理与实务》三个科目。其中《机电工程管理与实务》是专业科目&#xff0c;也是考试重点&#xff0c;主要考查机电工程技术、机电工程相关法规与标准、机电工程项目管理实务等内容。具体如下…

React + ts + react-webcam + CamSplitter 实现虚拟摄像头解决win摄像头独占的问题

一、安装 CamSplitter 这块网上有很多教程了&#xff0c;这里不再赘述&#xff0c;就一点&#xff0c;需要分几个虚拟摄像头&#xff0c;就要在CamSplitter 的安装目录下 driver_install.cmd 执行几次。二、React ts react-webcam 调用虚拟摄像头import { useState, useEffec…

【深度学习①】 | Numpy数组篇

0 序言 本文为NumPy数组库的系统学习笔记&#xff0c;将自己先前的笔记做一个总结归纳。内容涵盖数组基础、创建、索引、变形、运算、函数、布尔型数组及与张量的衔接等内容。通过具体示例解析核心概念与操作&#xff0c;帮助读者掌握NumPy的使用逻辑与方法&#xff0c;为后续深…

5.实现 call

call 是 JavaScript 中非常核心的函数方法之一。它能改变函数的执行上下文&#xff08;也就是 this 的指向&#xff09;&#xff0c;在日常开发和面试中都极其常见。本文将带你一步步实现一个 Function.prototype.call 的自定义版本&#xff0c;真正理解它的底层原理。✨ 一、c…

Go语言中的盲点:竞态检测和互斥锁的错觉

&#x1f9e0; Go语言中的盲点&#xff1a;竞态检测和互斥锁的错觉 使用 -race 就能发现所有并发问题&#xff1f;加了 mutex 就万无一失&#xff1f; 这篇文章揭示了 Go 并发编程中的一个“危险盲区” —— 互斥锁并不能总能保护你免受数据竞争的影响&#xff0c;尤其是在 -ra…

从文件到文件描述符:理解程序与文件的交互本质

一、理解文件 抛一个概念&#xff1a; 文件 内容 属性。 1. 那么&#xff0c;空文件有大小吗&#xff1f;答案是有的。因为空文件指的是文件内容为空&#xff0c;文件属性也要占据大小啊。 将来对文件操作&#xff0c;无非分为两类&#xff1a; 1.对文件内容做修改。 2.对文件…