Django ORM系统

1. ORM基础概念

1.1 什么是ORM?

ORM(Object Relational Mapping,对象关系映射)是一种编程技术,用于在面向对象编程语言中实现不同类型系统的数据转换。在Django中,ORM充当业务逻辑层和数据库层之间的桥梁。

核心映射关系

  • 类(Class) ↔ 数据库表(Table)

  • 类实例(Instance) ↔ 表记录(Row)

  • 类属性(Attribute) ↔ 表字段(Field)

1.2 ORM的优势

  1. 开发效率高:不用编写SQL语句,通过操作对象即可完成数据库操作

  2. 数据库解耦:更换数据库只需修改配置,无需更改业务代码

  3. 安全性:自动防止SQL注入攻击

  4. 维护性:模型集中管理,结构清晰

1.3 ORM的劣势

  1. 性能损耗:相比原生SQL有一定性能损失

  2. 复杂查询受限:某些复杂查询难以用ORM表达

  3. SQL能力退化:过度依赖ORM可能导致SQL能力下降

2. Django模型基础

2.1 模型定义

from django.db import modelsclass Book(models.Model):title = models.CharField(max_length=100)price = models.DecimalField(max_digits=5, decimal_places=2)publish_date = models.DateField(auto_now_add=True)

2.2 常用字段类型

字段类型说明示例
AutoField自增IDid = models.AutoField(primary_key=True)
CharField字符串name = models.CharField(max_length=32)
IntegerField整数age = models.IntegerField()
BooleanField布尔值is_active = models.BooleanField(default=True)
DateField日期birthday = models.DateField()
DateTimeField日期时间created = models.DateTimeField(auto_now_add=True)
EmailField邮箱email = models.EmailField()
TextField长文本content = models.TextField()
ForeignKey外键publisher = models.ForeignKey('Publisher')
ManyToManyField多对多authors = models.ManyToManyField('Author')

2.3 字段常用参数

参数说明示例
null数据库是否可为空null=True
blank表单验证是否可为空blank=True
default默认值default=0
primary_key是否主键primary_key=True
unique是否唯一unique=True
db_index是否创建索引db_index=True
choices可选值列表GENDER_CHOICES = [(0,'男'),(1,'女')]
verbose_name可读名称verbose_name='书名'

3. 数据库操作

3.1 增删改查(CRUD)

创建数据
# 方法1
Book.objects.create(title='Python入门', price=59.99)# 方法2
book = Book(title='Django高级', price=79.99)
book.save()# 方法3(批量创建)
Book.objects.bulk_create([Book(title='Java基础', price=49.99),Book(title='C++编程', price=69.99)
])
查询数据
# 获取所有
books = Book.objects.all()# 获取单个(不存在会报DoesNotExist)
book = Book.objects.get(id=1)# 过滤查询
cheap_books = Book.objects.filter(price__lt=50)# 排除查询
expensive_books = Book.objects.exclude(price__lt=100)# 排序
books = Book.objects.order_by('-price')# 限制数量
books = Book.objects.all()[:5]
更新数据
# 方法1
Book.objects.filter(id=1).update(price=99.99)# 方法2
book = Book.objects.get(id=1)
book.price = 89.99
book.save()
删除数据
# 删除单个
Book.objects.get(id=1).delete()# 批量删除
Book.objects.filter(price__gt=100).delete()

3.2 高级查询

双下划线查询
# 范围查询
Book.objects.filter(price__range=(50, 100))# 包含查询
Book.objects.filter(title__contains='Python')# 开头/结尾查询
Book.objects.filter(title__startswith='Django')
Book.objects.filter(title__endswith='入门')# 日期查询
Book.objects.filter(publish_date__year=2023)
Q对象(复杂查询)
from django.db.models import Q# OR查询
Book.objects.filter(Q(price__lt=50) | Q(title__contains='Python'))# NOT查询
Book.objects.filter(~Q(price__gt=100))# 组合查询
Book.objects.filter(Q(price__lt=50) & Q(title__startswith='Django'))
F对象(字段比较)
from django.db.models import F# 比较两个字段
Book.objects.filter(price__gt=F('discount_price'))# 字段运算
Book.objects.update(price=F('price') * 1.1)

3.3 聚合与分组

from django.db.models import Count, Avg, Max, Min, Sum# 聚合
Book.objects.aggregate(Avg('price'), Max('price'))# 分组
from django.db.models import Count
Publisher.objects.annotate(book_count=Count('book')).values('name', 'book_count')

4. 表关系操作

4.1 一对一关系

class UserProfile(models.Model):user = models.OneToOneField(User, on_delete=models.CASCADE)phone = models.CharField(max_length=20)# 查询
profile = user.userprofile
user = profile.user

4.2 一对多关系

class Publisher(models.Model):name = models.CharField(max_length=50)class Book(models.Model):publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)# 正向查询
book = Book.objects.first()
publisher = book.publisher# 反向查询
publisher = Publisher.objects.first()
books = publisher.book_set.all()

4.3 多对多关系

class Author(models.Model):name = models.CharField(max_length=50)class Book(models.Model):authors = models.ManyToManyField(Author)# 查询
book = Book.objects.first()
authors = book.authors.all()author = Author.objects.first()
books = author.book_set.all()# 添加关系
book.authors.add(author)
book.authors.remove(author)
book.authors.clear()
book.authors.set([author1, author2])

4.4 自定义中间表

class BookAuthor(models.Model):book = models.ForeignKey(Book, on_delete=models.CASCADE)author = models.ForeignKey(Author, on_delete=models.CASCADE)created = models.DateTimeField(auto_now_add=True)class Book(models.Model):authors = models.ManyToManyField(Author, through='BookAuthor')

5. 事务与原生SQL

5.1 事务处理

from django.db import transaction# 装饰器方式
@transaction.atomic
def create_book():# 这里的操作都在一个事务中pass# 上下文管理器方式
def update_book():try:with transaction.atomic():# 事务操作passexcept Exception:# 异常处理pass

5.2 执行原生SQL

from django.db import connection# 查询
with connection.cursor() as cursor:cursor.execute("SELECT * FROM books WHERE price > %s", [50])rows = cursor.fetchall()# 插入/更新
with connection.cursor() as cursor:cursor.execute("UPDATE books SET price = price * 1.1 WHERE publish_date > %s", ['2023-01-01'])

6. 性能优化

6.1 select_related(外键关联查询)

# 普通查询(会产生N+1问题)
books = Book.objects.all()
for book in books:print(book.publisher.name)  # 每次循环都会查询数据库# 优化查询(使用JOIN)
books = Book.objects.select_related('publisher').all()
for book in books:print(book.publisher.name)  # 只查询一次数据库

6.2 prefetch_related(多对多关联查询)

# 普通查询
authors = Author.objects.all()
for author in authors:print(author.book_set.all())  # 每次循环都会查询数据库# 优化查询
authors = Author.objects.prefetch_related('book_set').all()
for author in authors:print(author.book_set.all())  # 只查询两次数据库

6.3 only与defer

# 只获取指定字段
books = Book.objects.only('title', 'price')# 排除指定字段
books = Book.objects.defer('content')

6.4 批量操作

# 批量创建
Book.objects.bulk_create([...])# 批量更新
books = Book.objects.all()
for book in books:book.price *= 1.1
Book.objects.bulk_update(books, ['price'])

7. 实际应用案例

7.1 分页查询

from django.core.paginator import Paginatordef book_list(request):page = request.GET.get('page', 1)paginator = Paginator(Book.objects.all(), 10)books = paginator.get_page(page)return render(request, 'book_list.html', {'books': books})

7.2 复杂查询示例

# 查询2023年出版的,价格大于50或者标题包含"Python"的书籍
from django.db.models import Q
books = Book.objects.filter(Q(publish_date__year=2023) &(Q(price__gt=50) | Q(title__icontains='Python'))
).order_by('-publish_date')

7.3 自定义管理器

class ActiveBookManager(models.Manager):def get_queryset(self):return super().get_queryset().filter(is_active=True)class Book(models.Model):is_active = models.BooleanField(default=True)objects = models.Manager()  # 默认管理器active = ActiveBookManager()  # 自定义管理器# 使用
active_books = Book.active.all()

8. 常见问题与解决方案

Q1: 如何查看ORM生成的SQL语句?

# 方法1:打印QuerySet的query属性
print(Book.objects.all().query)# 方法2:配置LOGGING
LOGGING = {'version': 1,'handlers': {'console': {'level': 'DEBUG','class': 'logging.StreamHandler',},},'loggers': {'django.db.backends': {'level': 'DEBUG','handlers': ['console'],},},
}

Q2: 如何优化ORM查询性能?

  1. 使用select_relatedprefetch_related减少查询次数

  2. 使用onlydefer限制查询字段

  3. 合理使用索引(db_index=True

  4. 批量操作代替循环操作

  5. 避免在循环中进行数据库查询

Q3: 如何处理大量数据?

# 使用iterator()方法
for book in Book.objects.all().iterator():process(book)# 使用分块查询
from django.core.paginator import Paginator
paginator = Paginator(Book.objects.all(), 1000)
for page in paginator.page_range:for book in paginator.page(page).object_list:process(book)

Q4: 如何实现软删除?

class SoftDeleteModel(models.Model):is_deleted = models.BooleanField(default=False)def delete(self, using=None, keep_parents=False):self.is_deleted = Trueself.save()class Meta:abstract = Trueclass Book(SoftDeleteModel):# 其他字段...pass# 查询时排除已删除
Book.objects.filter(is_deleted=False)

9. 总结

Django ORM是一个功能强大且易于使用的数据库抽象层,通过本文我们学习了:

  1. 模型定义:如何定义模型和字段

  2. 基本CRUD:创建、读取、更新和删除操作

  3. 高级查询:Q对象、F对象、聚合和分组

  4. 表关系:一对一、一对多和多对多关系的处理

  5. 性能优化:select_related、prefetch_related等技巧

  6. 事务管理:保证数据一致性的方法

  7. 实际应用:分页、复杂查询等常见场景

掌握这些知识后,你将能够高效地使用Django ORM进行数据库操作,同时保持代码的清晰和可维护性。记住,ORM是工具,合理使用才能发挥最大价值。

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

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

相关文章

Tailwind CSS中设定宽度和高度的方法

在 Tailwind CSS 中,设定元素的宽度(width)和高度(height)有多种方式,涵盖固定值、相对值、响应式调整等。以下是完整的方法分类及示例:一、固定宽度 / 高度类以 4px (0.25rem) 为单位递增&…

Java行为型模式---备忘录模式

备忘录模式基础概念备忘录模式(Memento Pattern)是一种行为型设计模式,其核心思想是在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便后续可以将该对象恢复到先前保存的状态…

后端参数校验

前端给后端传输数据&#xff0c;有时候参数需要校验&#xff0c;我们自己写代码会比较麻烦&#xff0c;我们可以使用springboot为我们提供的注解&#xff0c;降低这些没有必要的代码开发。1.引入依赖<dependency><groupId>org.springframework.boot</groupId>…

C++ - 仿 RabbitMQ 实现消息队列--服务端核心模块实现(一)

目录 日志打印工具 实用 Helper 工具 sqlite 基础操作类 字符串操作类 UUID 生成器类 文件基础操作 文件是否存在判断 文件大小获取 读文件 写文件 文件重命名 文件创建/删除 父级目录的获取 目录创建/删除 附录&#xff08;完整代码&#xff09; 日志打印工具 为了便…

C语言:第07天笔记

C语言&#xff1a;第07天笔记 内容提要 循环结构 break与continue 综合案例《猜拳游戏》数组 数组的概念一维数组流程控制 break与continue break 功能&#xff1a; ① 用在switch中&#xff0c;用来跳出switch中的case语句&#xff1b;如果case没有break&#xff0c;可能会产生…

qt 中英文翻译 如何配置和使用

qt 中英文翻译 如何配置和使用 1. 在.pro文件中添加TRANSLATIONS 在你的 .pro 文件&#xff08;比如 HYAC_AAF_HOST.pro&#xff09;中添加&#xff1a; TRANSLATIONS \ zh\_CN.ts en\_US.ts这会告诉Qt项目你要支持中文和英文。 2. 提取可翻译文本&#xff08;生成ts文件&#…

Leetcode 710. 黑名单中的随机数

1.题目基本信息 1.1.题目描述 给定一个整数 n 和一个 无重复 黑名单整数数组 blacklist 。设计一种算法&#xff0c;从 [0, n - 1] 范围内的任意整数中选取一个 未加入 黑名单 blacklist 的整数。任何在上述范围内且不在黑名单 blacklist 中的整数都应该有 同等的可能性 被返…

RxJava 全解析:从原理到 Android 实战

在 Android 开发中&#xff0c;异步任务处理是绕不开的核心场景 —— 网络请求、数据库操作、文件读写等都需要在后台执行&#xff0c;而结果需回调到主线程更新 UI。传统的 “HandlerThread” 或 AsyncTask 不仅代码冗余&#xff0c;还容易陷入 “回调地狱”&#xff08;嵌套回…

OpenCV 官翻7 - 对象检测

文章目录ArUco 标记检测标记与字典标记物创建标记检测姿态估计选择字典预定义字典自动生成字典手动定义字典检测器参数阈值处理adaptiveThreshConstant轮廓过滤minMarkerPerimeterRate 与 maxMarkerPerimeterRatepolygonalApproxAccuracyRateminCornerDistanceRateminMarkerDis…

【Oracle】ORACLE OMF说明

ORACLE OMF (Oracle Managed Files) 是 Oracle 数据库提供的一项自动化文件管理功能。它的核心目的是简化数据库管理员&#xff08;DBA&#xff09;对数据库底层操作系统文件的管理工作。 以下是 OMF 的关键要点&#xff1a; 核心功能&#xff1a;自动命名和定位文件 在创建数据…

408考研逐题详解:2010年第35题——RIP协议

2010年第35题 某自治系统内采用 RIP 协议&#xff0c;若该自治系统内的路由器 R1 收到其邻居路由器 R2 的距离矢量&#xff0c;距离矢量中包含信息 <net1, 16>&#xff0c;则能得出的结论是&#xff08; &#xff09; A. R2 可以经过 R1 到达 net1&#xff0c;跳数为17 …

http与https的主要区别是什么?

什么是HTTP&#xff1f; HTTP&#xff08;HyperText Transfer Protocol&#xff0c;超文本传输协议&#xff09;是互联网上应用最为广泛的一种网络协议。它构成了Web数据通信的基础&#xff0c;并定义了客户端和服务器之间如何请求和传递网页信息。当您在浏览器中输入一个网址时…

STC89C52系列单片机简介

STC89C52系列单片机是由中国宏晶科技&#xff08;STC&#xff09;推出的一款新一代增强型8051内核单片机。它不仅继承了传统8051指令系统的兼容性&#xff0c;还在性能、功耗、抗干扰能力以及性价比方面进行了全面提升&#xff0c;广泛应用于各类嵌入式控制场景&#xff0c;如工…

基于 Docker 环境的 JupyterHub 详细部署手册

本文详细介绍基于Docker Compose的单机版JupyterHub部署方案&#xff0c;通过容器化技术实现多用户Notebook环境的快速搭建。方案采用官方JupyterHub镜像&#xff0c;配置11个端口映射&#xff08;18000-18010&#xff09;支持用户并发&#xff0c;通过数据卷挂载&#xff08;.…

常见的万能密码

目录 1. 通用SQL注入 2. 登录绕过 3. 密码重置 1. 通用SQL注入 or 11-- " or 11-- or aa " or "a""a or 11# " or 11# or 11/* " or 11/* or 11 " or "1""1 2. 登录绕过 admin-- admin or 11-- admin or aa …

04训练windows电脑低算力显卡如何部署pytorch实现GPU加速

大多数人用的电脑的显卡配置可能没有那么强,也就是说,我们很难享受到最新版本pytorch给我们带来的模型训练的速度和效率,为此,我们需要想办法在现有显卡情况下部署应用pytorch。 笔者有一台电脑,显卡算力很低,那么以该电脑为例,为大家介绍如何部署应用pytorch功能。 1…

PPT科研画图插件

PPT科研画图插件 iSlide- 让PPT设计简单起来 | PPT模板下载平台iSlide - 简单&#xff0c;好用的PPT插件&#xff01;拥有30万 原创可商用PPT模板&#xff0c;PPT主题素材&#xff0c;PPT案例&#xff0c;PPT图表&#xff0c;PPT图示&#xff0c;PPT图标&#xff0c;PPT插图和8…

CSS实现背景图片渐变透明

复合写法background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #FFF 82.5%),url(https://example.com/image.jpg) center / cover no-repeat;参数说明&#xff1a;linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, #FFF 82.5%)创建从下至上的垂直渐变&#xff…

基于pyside6的通用机器人遥控控制界面

1. 前言 这两天需要帮一个朋友做一个简单的遥控控制界面&#xff0c;用于控制一台复合机器人(万向轮底盘机械臂旋转云台)&#xff0c;在这里分享一下 2. 开发框架 由于朋友那边的控制接口都是使用python来写的&#xff0c;所以我这里也使用py来完成这个遥控界面的开发。但其…

【iOS】ZARA仿写

【iOS】ZARA仿写 文章目录【iOS】ZARA仿写前言首页发现我的对姓名的更改总结前言 暑假第一个的任务仿写ZARA 虽然不是特别难却有很多小细节需要注意 首页 点进程序出现的就是整个项目最主要的一个点&#xff0c;即首页的无限轮播图&#xff0c;不管是自动轮播还是手动滑动&a…