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

相关推荐
两圆相切1 小时前
Oracle触发器:数据世界的“隐形守护者“
数据库·oracle
掘根2 小时前
【MySQL进阶】三大范式
数据库·mysql·oracle
深度学习04073 小时前
【Linux服务器】-MySQL数据库参数调优
linux·服务器·数据库
别致的影分身5 小时前
MySQL InnoDB 存储引擎
数据库·mysql
青草地溪水旁8 小时前
`MYSQL`、`MYSQL_RES` 和 `MYSQL_FIELD`的含义与使用案例
数据库·mysql·c
程序猿小D8 小时前
基于SpringBoot+MyBatis+MySQL+VUE实现的医疗挂号管理系统(附源码+数据库+毕业论文+答辩PPT+项目部署视频教程+项目所需软件工具)
数据库·vue.js·spring boot·mysql·毕业设计·mybatis·医疗挂号管理系统
万粉变现经纪人8 小时前
如何解决pip安装报错ModuleNotFoundError: No module named ‘django’问题
后端·python·pycharm·django·numpy·pandas·pip
仰望星空的凡人9 小时前
【JS逆向基础】数据库之mysql
javascript·数据库·python·mysql
大大大水蜜桃9 小时前
sql练习二
java·数据库·sql