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 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 | 自增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():# 事務操作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查詢性能?
使用
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 = Trueself.save()class Meta:abstract = Trueclass Book(SoftDeleteModel):# 其他字段...pass# 查詢時排除已刪除
Book.objects.filter(is_deleted=False)
9. 總結
Django ORM是一個功能強大且易于使用的數據庫抽象層,通過本文我們學習了:
模型定義:如何定義模型和字段
基本CRUD:創建、讀取、更新和刪除操作
高級查詢:Q對象、F對象、聚合和分組
表關系:一對一、一對多和多對多關系的處理
性能優化:select_related、prefetch_related等技巧
事務管理:保證數據一致性的方法
實際應用:分頁、復雜查詢等常見場景
掌握這些知識后,你將能夠高效地使用Django ORM進行數據庫操作,同時保持代碼的清晰和可維護性。記住,ORM是工具,合理使用才能發揮最大價值。