1. ORM基础概念
1.1 什么是ORM?
ORM(Object Relational Mapping,对象关系映射)是一种编程技术,用于在面向对象编程语言中实现不同类型系统的数据转换。在Django中,ORM充当业务逻辑层和数据库层之间的桥梁。
核心映射关系:
-
类(Class) ↔ 数据库表(Table)
-
类实例(Instance) ↔ 表记录(Row)
-
类属性(Attribute) ↔ 表字段(Field)
1.2 ORM的优势
-
开发效率高:不用编写SQL语句,通过操作对象即可完成数据库操作
-
数据库解耦:更换数据库只需修改配置,无需更改业务代码
-
安全性:自动防止SQL注入攻击
-
维护性:模型集中管理,结构清晰
1.3 ORM的劣势
-
性能损耗:相比原生SQL有一定性能损失
-
复杂查询受限:某些复杂查询难以用ORM表达
-
SQL能力退化:过度依赖ORM可能导致SQL能力下降
2. Django模型基础
2.1 模型定义
from django.db import models
class 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 | 自增ID | id = 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():
# 事务操作
pass
except 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 Paginator
def 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查询性能?
-
使用
select_related
和prefetch_related
减少查询次数 -
使用
only
和defer
限制查询字段 -
合理使用索引(
db_index=True
) -
批量操作代替循环操作
-
避免在循环中进行数据库查询
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 = True
self.save()
class Meta:
abstract = True
class Book(SoftDeleteModel):
# 其他字段...
pass
# 查询时排除已删除
Book.objects.filter(is_deleted=False)
9. 总结
Django ORM是一个功能强大且易于使用的数据库抽象层,通过本文我们学习了:
-
模型定义:如何定义模型和字段
-
基本CRUD:创建、读取、更新和删除操作
-
高级查询:Q对象、F对象、聚合和分组
-
表关系:一对一、一对多和多对多关系的处理
-
性能优化:select_related、prefetch_related等技巧
-
事务管理:保证数据一致性的方法
-
实际应用:分页、复杂查询等常见场景
掌握这些知识后,你将能够高效地使用Django ORM进行数据库操作,同时保持代码的清晰和可维护性。记住,ORM是工具,合理使用才能发挥最大价值。