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 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查询性能?

  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 = True
        self.save()
    
    class Meta:
        abstract = True

class 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是工具,合理使用才能发挥最大价值。

相关推荐
阿里小阿希4 小时前
Vue3 + Element Plus 项目中日期时间处理的最佳实践与数据库设计规范
数据库·设计规范
白鹭5 小时前
MySQL源码部署(rhel7)
数据库·mysql
666和7775 小时前
Struts2 工作总结
java·数据库
还听珊瑚海吗5 小时前
SpringMVC(一)
数据库
星期天要睡觉6 小时前
MySQL 综合练习
数据库·mysql
Y4090017 小时前
数据库基础知识——聚合函数、分组查询
android·数据库
JosieBook7 小时前
【数据库】MySQL 数据库创建存储过程及使用场景详解
数据库·mysql
处女座_三月8 小时前
改 TDengine 数据库的时间写入限制
数据库·sql·mysql