Django ORM单表操作全解析:从基础CRUD到高级查询 📅 发布时间:2026/9/11 10:29:21 👁 浏览次数: 1. Django ORM 单表操作基础概念Django ORMObject-Relational Mapping是Django框架中最强大的功能之一它允许开发者使用Python类和方法来操作数据库而无需直接编写SQL语句。单表操作是ORM中最基础也是最常用的功能掌握好单表操作是使用Django ORM的第一步。在Django中每个模型类对应数据库中的一张表。当我们定义一个模型类时Django会自动为我们创建对应的数据库表结构。例如我们定义一个简单的Book模型from django.db import models class Book(models.Model): title models.CharField(max_length100) author models.CharField(max_length50) publish_date models.DateField() price models.DecimalField(max_digits5, decimal_places2) def __str__(self): return self.title这个简单的模型类定义了四个字段title书名、author作者、publish_date出版日期和price价格。Django会自动为这个模型创建对应的数据库表表名默认为appname_book假设这个模型在名为books的app中。注意在Django中每个模型类必须继承自django.db.models.Model类这是Django ORM工作的基础。2. 单表CRUD操作详解2.1 创建记录Create在Django ORM中创建新记录有几种不同的方式使用create()方法Book.objects.create( titlePython编程从入门到实践, authorEric Matthes, publish_date2020-05-01, price89.00 )先创建模型实例再保存new_book Book( title流畅的Python, authorLuciano Ramalho, publish_date2017-05-01, price109.00 ) new_book.save()使用get_or_create()方法避免重复创建book, created Book.objects.get_or_create( titlePython编程从入门到实践, defaults{ author: Eric Matthes, publish_date: 2020-05-01, price: 89.00 } )提示get_or_create()方法返回一个元组第一个元素是获取或创建的对象第二个元素是布尔值表示对象是否是新创建的。2.2 查询记录ReadDjango ORM提供了丰富的查询API以下是一些常用的查询方法获取所有记录all_books Book.objects.all()获取单条记录通过主键book Book.objects.get(pk1)条件查询# 价格大于100的书 expensive_books Book.objects.filter(price__gt100) # 作者是Eric Matthes的书 eric_books Book.objects.filter(authorEric Matthes) # 2020年出版的书 books_2020 Book.objects.filter(publish_date__year2020)链式查询# 2020年出版且价格大于80的书 books Book.objects.filter(publish_date__year2020).filter(price__gt80)排序# 按价格升序 books_asc Book.objects.all().order_by(price) # 按价格降序 books_desc Book.objects.all().order_by(-price)2.3 更新记录Update更新记录也有几种方式先获取对象再修改属性并保存book Book.objects.get(pk1) book.price 99.00 book.save()使用update()方法批量更新# 将所有Eric Matthes的书价格设为95 Book.objects.filter(authorEric Matthes).update(price95)注意update()方法直接生成SQL语句执行更新不会调用模型的save()方法也不会触发pre_save或post_save信号。2.4 删除记录Delete删除记录同样有多种方式删除单个对象book Book.objects.get(pk1) book.delete()批量删除# 删除所有价格低于50的书 Book.objects.filter(price__lt50).delete()删除所有记录Book.objects.all().delete()警告delete()操作是不可逆的执行前务必确认数据备份或确认操作无误。3. 高级查询技巧3.1 字段查询条件Django ORM提供了丰富的字段查询条件exact精确匹配默认Book.objects.filter(title__exactPython编程)iexact不区分大小写的精确匹配Book.objects.filter(title__iexactpython编程)contains包含Book.objects.filter(title__containsPython)icontains不区分大小写的包含Book.objects.filter(title__icontainspython)in在某个列表中Book.objects.filter(price__in[89, 99, 109])gt/gte/lt/lte大于/大于等于/小于/小于等于Book.objects.filter(price__gt100)startswith/istartswith以...开头Book.objects.filter(title__startswithPython)endswith/iendswith以...结尾Book.objects.filter(title__endswith实践)range范围查询import datetime start_date datetime.date(2020, 1, 1) end_date datetime.date(2020, 12, 31) Book.objects.filter(publish_date__range(start_date, end_date))3.2 聚合与分组Django ORM支持各种聚合操作计数from django.db.models import Count Book.objects.aggregate(totalCount(id))平均值from django.db.models import Avg Book.objects.aggregate(avg_priceAvg(price))最大值/最小值from django.db.models import Max, Min Book.objects.aggregate( max_priceMax(price), min_priceMin(price) )分组统计from django.db.models import Count # 按作者统计书籍数量 Book.objects.values(author).annotate(book_countCount(id))3.3 F表达式和Q对象F表达式用于在查询中引用字段的值from django.db.models import F # 将所有书的价格增加10元 Book.objects.all().update(priceF(price) 10)Q对象用于构建复杂的查询条件from django.db.models import Q # 查找作者是Eric Matthes或价格大于100的书 Book.objects.filter(Q(authorEric Matthes) | Q(price__gt100)) # 查找书名包含Python但不包含入门的书 Book.objects.filter( Q(title__containsPython) ~Q(title__contains入门) )4. 性能优化与常见问题4.1 查询性能优化使用select_related和prefetch_related虽然本文讲单表但这是ORM重要概念# 假设Book有一个外键publisher books Book.objects.select_related(publisher).all()使用only和defer控制查询字段# 只查询title和author字段 books Book.objects.only(title, author) # 查询除price外的所有字段 books Book.objects.defer(price)使用values和values_list获取特定字段# 返回字典列表 books Book.objects.values(title, author) # 返回元组列表 books Book.objects.values_list(title, author)避免N1查询问题# 不好的做法会导致N1查询 for book in Book.objects.all(): print(book.publisher.name) # 每次循环都会查询一次publisher # 好的做法 for book in Book.objects.select_related(publisher).all(): print(book.publisher.name) # 只查询一次4.2 常见问题与解决方案DoesNotExist异常try: book Book.objects.get(pk1000) # 假设不存在 except Book.DoesNotExist: print(书籍不存在)MultipleObjectsReturned异常try: book Book.objects.get(titlePython编程) # 假设有多本同名书 except Book.MultipleObjectsReturned: print(找到多本同名书籍)批量操作性能问题# 不好的做法每次循环都执行一次SQL for i in range(1000): Book.objects.create(titlefBook {i}, authorAuthor, price10) # 好的做法使用bulk_create books [Book(titlefBook {i}, authorAuthor, price10) for i in range(1000)] Book.objects.bulk_create(books)事务处理from django.db import transaction try: with transaction.atomic(): # 一系列数据库操作 book1 Book.objects.create(titleBook 1, price10) book2 Book.objects.create(titleBook 2, price20) # 如果这里出错前面的创建操作也会回滚 except Exception as e: print(f操作失败: {e})5. 实际应用案例5.1 书籍管理系统基础功能实现假设我们要实现一个简单的书籍管理系统以下是一些基础功能的实现添加新书def add_book(title, author, publish_date, price): try: book Book.objects.create( titletitle, authorauthor, publish_datepublish_date, priceprice ) return True, 添加成功 except Exception as e: return False, f添加失败: {e}搜索书籍def search_books(keywordNone, authorNone, min_priceNone, max_priceNone): query Q() if keyword: query Q(title__icontainskeyword) if author: query Q(author__icontainsauthor) if min_price is not None: query Q(price__gtemin_price) if max_price is not None: query Q(price__ltemax_price) return Book.objects.filter(query).order_by(-publish_date)更新书籍价格def update_book_price(book_id, new_price): try: book Book.objects.get(pkbook_id) book.price new_price book.save() return True, 更新成功 except Book.DoesNotExist: return False, 书籍不存在 except Exception as e: return False, f更新失败: {e}删除书籍def delete_book(book_id): try: book Book.objects.get(pkbook_id) book.delete() return True, 删除成功 except Book.DoesNotExist: return False, 书籍不存在 except Exception as e: return False, f删除失败: {e}5.2 数据统计功能书籍价格统计def get_price_stats(): from django.db.models import Avg, Max, Min, Count return Book.objects.aggregate( totalCount(id), avg_priceAvg(price), max_priceMax(price), min_priceMin(price) )按作者统计def get_author_stats(): from django.db.models import Count, Avg return Book.objects.values(author).annotate( book_countCount(id), avg_priceAvg(price) ).order_by(-book_count)年度出版统计def get_yearly_stats(): from django.db.models import Count from django.db.models.functions import ExtractYear return Book.objects.annotate( yearExtractYear(publish_date) ).values(year).annotate( countCount(id) ).order_by(year)6. 最佳实践与经验分享6.1 模型设计建议为常用查询字段添加db_indexclass Book(models.Model): title models.CharField(max_length100, db_indexTrue) author models.CharField(max_length50, db_indexTrue) # 其他字段...为模型添加Meta选项class Book(models.Model): # 字段定义... class Meta: ordering [-publish_date] # 默认排序 verbose_name 图书 # 在admin中显示的名称 verbose_name_plural 图书 # 复数形式 indexes [ models.Index(fields[author, publish_date]), ]使用choices限制字段可选值class Book(models.Model): CATEGORY_CHOICES [ (TECH, 技术), (LIT, 文学), (HIS, 历史), ] category models.CharField( max_length4, choicesCATEGORY_CHOICES, defaultTECH ) # 其他字段...6.2 查询优化经验使用explain()分析查询性能# 查看查询执行计划 print(Book.objects.filter(price__gt100).explain())避免在循环中执行查询# 不好的做法 authors [Author1, Author2, Author3] books [] for author in authors: books.extend(Book.objects.filter(authorauthor)) # 好的做法 books Book.objects.filter(author__inauthors)使用iterator()处理大量数据# 处理大量数据时节省内存 for book in Book.objects.all().iterator(): process_book(book)使用count()代替len(queryset)# 不好的做法会加载所有数据到内存 count len(Book.objects.all()) # 好的做法使用数据库的count函数 count Book.objects.count()6.3 调试技巧查看生成的SQL语句# 方法1使用query属性 queryset Book.objects.filter(price__gt100) print(queryset.query) # 方法2使用connection.queries from django.db import connection queryset Book.objects.filter(price__gt100) list(queryset) # 执行查询 print(connection.queries)使用django-debug-toolbar# 安装后可以直观查看查询性能 # pip install django-debug-toolbar日志记录数据库查询# 在settings.py中添加 LOGGING { version: 1, handlers: { console: { level: DEBUG, class: logging.StreamHandler, }, }, loggers: { django.db.backends: { level: DEBUG, handlers: [console], }, }, }