Django模型查询
外观
Django模型查询[编辑 | 编辑源代码]
Django模型查询是Django ORM(对象关系映射)的核心功能之一,允许开发者通过Python代码与数据库交互,而无需直接编写SQL语句。它提供了丰富的API来执行数据库的增删改查(CRUD)操作,同时保持代码的简洁性和可维护性。
基础查询方法[编辑 | 编辑源代码]
Django模型查询主要通过模型的objects
管理器进行。以下是几种常用的基础查询方法:
all()[编辑 | 编辑源代码]
获取模型的所有记录:
from myapp.models import Book
# 获取所有图书
all_books = Book.objects.all()
# 输出前5本图书的标题
for book in all_books[:5]:
print(book.title)
filter()[编辑 | 编辑源代码]
根据条件筛选记录:
# 获取所有价格大于20的图书
expensive_books = Book.objects.filter(price__gt=20)
# 获取作者是"John Doe"的图书
johns_books = Book.objects.filter(author="John Doe")
get()[编辑 | 编辑源代码]
获取单个记录(如果找不到或找到多个会抛出异常):
try:
# 获取ID为1的图书
specific_book = Book.objects.get(id=1)
print(specific_book.title)
except Book.DoesNotExist:
print("图书不存在")
except Book.MultipleObjectsReturned:
print("找到多个图书")
查询字段查找[编辑 | 编辑源代码]
Django提供了多种字段查找方式(Field Lookups),用于在filter()
、exclude()
和get()
中指定条件:
查找类型 | 描述 | 示例 |
---|---|---|
exact |
精确匹配 | Book.objects.filter(title__exact="Django")
|
iexact |
不区分大小写的精确匹配 | Book.objects.filter(title__iexact="django")
|
contains |
包含 | Book.objects.filter(title__contains="Python")
|
icontains |
不区分大小写的包含 | Book.objects.filter(title__icontains="python")
|
in |
在列表中 | Book.objects.filter(id__in=[1, 3, 5])
|
gt |
大于 | Book.objects.filter(price__gt=20)
|
gte |
大于等于 | Book.objects.filter(price__gte=15)
|
lt |
小于 | Book.objects.filter(price__lt=10)
|
lte |
小于等于 | Book.objects.filter(price__lte=15)
|
startswith |
以...开头 | Book.objects.filter(title__startswith="The")
|
istartswith |
不区分大小写的以...开头 | Book.objects.filter(title__istartswith="the")
|
endswith |
以...结尾 | Book.objects.filter(title__endswith="Guide")
|
iendswith |
不区分大小写的以...结尾 | Book.objects.filter(title__iendswith="guide")
|
range |
范围 | Book.objects.filter(publish_date__range=("2020-01-01", "2020-12-31"))
|
isnull |
是否为NULL | Book.objects.filter(author__isnull=True)
|
复杂查询[编辑 | 编辑源代码]
Q对象[编辑 | 编辑源代码]
用于构建复杂的查询条件,支持逻辑或(OR)操作:
from django.db.models import Q
# 查找价格低于10或高于50的图书
books = Book.objects.filter(Q(price__lt=10) | Q(price__gt=50))
# 查找标题包含"Python"但不包含"Django"的图书
books = Book.objects.filter(Q(title__icontains="Python") & ~Q(title__icontains="Django"))
F对象[编辑 | 编辑源代码]
用于在查询中引用字段的值:
from django.db.models import F
# 查找库存数量小于已售数量的图书
books = Book.objects.filter(stock__lt=F('sold'))
# 将所有图书价格增加10
Book.objects.update(price=F('price') + 10)
聚合与注解[编辑 | 编辑源代码]
Django提供了强大的聚合功能:
聚合函数[编辑 | 编辑源代码]
from django.db.models import Avg, Max, Min, Sum
# 计算所有图书的平均价格
avg_price = Book.objects.aggregate(Avg('price'))
# 计算每个作者的图书最高价格
from django.db.models import Count
author_stats = Book.objects.values('author').annotate(
max_price=Max('price'),
book_count=Count('id')
)
注解[编辑 | 编辑源代码]
为查询集中的每个对象添加计算字段:
from django.db.models import Value
from django.db.models.functions import Concat
# 为每本图书添加全名字段
books = Book.objects.annotate(
full_name=Concat('title', Value(' by '), 'author')
)
查询优化[编辑 | 编辑源代码]
[编辑 | 编辑源代码]
用于外键关系的预取(JOIN操作):
# 获取图书及其出版社信息(一对一或外键关系)
books = Book.objects.select_related('publisher')
[编辑 | 编辑源代码]
用于多对多关系的预取:
# 获取图书及其所有标签(多对多关系)
books = Book.objects.prefetch_related('tags')
only/defer[编辑 | 编辑源代码]
控制加载的字段:
# 只加载title字段
books = Book.objects.only('title')
# 加载除description外的所有字段
books = Book.objects.defer('description')
实际案例[编辑 | 编辑源代码]
假设我们有一个图书管理系统,包含以下模型:
from django.db import models
class Author(models.Model):
name = models.CharField(max_length=100)
birth_date = models.DateField()
class Publisher(models.Model):
name = models.CharField(max_length=100)
founded = models.IntegerField()
class Book(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)
publish_date = models.DateField()
price = models.DecimalField(max_digits=5, decimal_places=2)
stock = models.IntegerField()
sold = models.IntegerField()
tags = models.ManyToManyField('Tag')
class Tag(models.Model):
name = models.CharField(max_length=50)
案例1:图书统计报表[编辑 | 编辑源代码]
from django.db.models import Count, Avg
# 获取每个出版社的图书数量、平均价格和总销量
report = Publisher.objects.annotate(
book_count=Count('book'),
avg_price=Avg('book__price'),
total_sold=Sum('book__sold')
).order_by('-book_count')
for publisher in report:
print(f"{publisher.name}: {publisher.book_count} books, "
f"avg price ${publisher.avg_price:.2f}, "
f"total sold {publisher.total_sold}")
案例2:图书推荐系统[编辑 | 编辑源代码]
# 查找与某本图书有相同标签的其他图书
def get_related_books(book_id, limit=5):
book = Book.objects.get(id=book_id)
related_books = Book.objects.filter(
tags__in=book.tags.all()
).exclude(
id=book_id
).distinct().order_by('?')[:limit]
return related_books
性能考虑[编辑 | 编辑源代码]
数学表达式[编辑 | 编辑源代码]
在聚合查询中,可能会用到一些数学表达式。例如计算折扣后的价格:
在Django中可以实现为:
from django.db.models import F, ExpressionWrapper, DecimalField
discounted_books = Book.objects.annotate(
discounted_price=ExpressionWrapper(
F('price') * (1 - F('discount_rate')/100),
output_field=DecimalField(max_digits=5, decimal_places=2)
)
)
总结[编辑 | 编辑源代码]
Django模型查询提供了强大而灵活的方式来与数据库交互,关键点包括:
- 使用
objects
管理器进行基本查询 - 掌握字段查找(Field Lookups)构建精确查询条件
- 使用Q对象和F对象实现复杂查询逻辑
- 通过聚合和注解实现数据分析功能
- 使用
select_related
和prefetch_related
优化查询性能 - 在实际应用中结合业务需求设计高效查询
通过合理使用这些功能,可以构建出既高效又易于维护的数据库查询代码。