深度探讨 Django ORM 的概念、根底应用、进阶操作以及具体解析在理论应用中如何解决数据库操作。同时,咱们还探讨了模型深刻了解,如何进行 CRUD 操作,并且深入了解到数据库迁徙等高级主题。为了全面解读 Django ORM,咱们也探讨了其存在的有余,并对其将来倒退进行了瞻望。这篇文章旨在帮忙读者全面把握 Django ORM,了解其如何简化数据库操作,并透过表象了解其外部工作原理。
Django ORM 简介
在深刻探讨 Django 的 ORM(Object-Relational Mapping,对象 - 关系映射)之前,让咱们先了解一下什么是 ORM。
ORM 是一种编程技术,用于在面向对象的软件和关系数据库之间建设一种可兼容的零碎。简略来说,ORM 可能让你应用 Python(或其余编程语言)来操作数据库,就像你在操作 Python 对象一样。
Django 的 ORM 是一个十分弱小的工具,它帮忙你治理和查询数据库。基于 Django ORM 的次要劣势,你能够:
- 利用 Python 的对象模型进行数据库查问,无需编写简单的 SQL 语句。
- 实现数据库的平台独立性,因为 Django ORM 能够在多种数据库系统上运行。
上面咱们用一个简略的例子来阐明这个概念。假如咱们有一个名为 ”Blog” 的模型,其中有一个名为 ”title” 的字段。应用 Django ORM,咱们能够轻松地查问所有题目蕴含 ”Django” 的博客。
# 导入模型
from myapp.models import Blog
# 应用 ORM 进行查问
blogs = Blog.objects.filter(title__contains='Django')
# 输入查问后果
for blog in blogs:
print(blog.title)
如果你在数据库中有名为 ”Learning Django” 和 ”Django ORM basics” 的博客,下面的代码将会输入:
Learning Django
Django ORM basics
看到这里,你可能会发现 Django ORM 的弱小之处:它把简单的数据库操作转化为 Python 对象操作,这极大地提高了咱们的编程效率。
Django ORM 运行机理与模型介绍
Django ORM 运行机理
Django ORM 将类(class)映射到数据库表(table),将类的实例(instance)映射到表的记录(record),将类的字段(field)映射到数据库的字段(column)。通过这种形式,你能够应用 Python 代码对数据库进行操作,而无需写任何 SQL 语句。
在 Django ORM 中,每个模型(model)对应一个数据库表,模型的字段对应表的列,模型的实例对应表的行。
Django 模型介绍
在 Django 中,模型是对数据库表的一种高级形象。通过定义一个模型,你能够明确地指定数据库的构造,包含数据表的名称、字段的名称和类型,以及可能的索引等。
让咱们看一个简略的例子,定义一个名为“Blog”的模型:
from django.db import models
class Blog(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
pub_date = models.DateTimeField(auto_now_add=True)
在这个例子中,咱们定义了一个名为 Blog
的模型,它有三个字段:title
、content
和 pub_date
。每个字段都对应一种数据库的列类型:CharField
对应字符类型,TextField
对应文本类型,DateTimeField
对应日期工夫类型。
Django 模型 Model 深刻了解
定义模型
在 Django 中,模型是数据拜访层的外围组成部分,它为你的数据定义了最重要的行为。模型是一个 Python 类,子类于django.db.models.Model
。每个模型都对应一个数据库表。
from django.db import models
class Blog(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
pub_date = models.DateTimeField(auto_now_add=True)
下面的例子中,咱们定义了一个名为 Blog
的模型,它有三个字段:title
、content
和pub_date
。
模型字段类型
Django 提供了许多内置的字段类型,能够满足大部分的数据库设计需要。例如:
CharField
:字符字段,用于存储较短的字符串,如题目。TextField
:文本字段,用于存储大量文本,如博客内容。DateTimeField
:日期工夫字段,用于存储日期和工夫。
每种字段类型都有其特定的参数,例如 CharField
须要一个 max_length
参数,指定该字段的最大长度。
模型关联关系
Django 的模型还能够定义简单的关联关系,包含一对一(OneToOne)、一对多(ForeignKey)和多对多(ManyToMany)关系。
例如,咱们能够定义一个 Author
模型,并将其与 Blog
模型关联:
class Author(models.Model):
name = models.CharField(max_length=100)
class Blog(models.Model):
title = models.CharField(max_length=200)
content = models.TextField()
pub_date = models.DateTimeField(auto_now_add=True)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
这里咱们为 Blog
模型增加了一个 author
字段,它是一个外键字段(ForeignKey
),指向 Author
模型。这意味着每篇博客都有一个作者,而每个作者能够写多篇博客。
当咱们删除一个作者时,on_delete=models.CASCADE
参数将确保所有关联的博客也会被删除。
Django ORM 增删改查 CRUD 操作
在理解了 Django 模型后,咱们来看看如何应用 Django ORM 进行常见的数据库操作:创立(Create)、读取(Retrieve)、更新(Update)和删除(Delete),通常被称为 CRUD 操作。
创立记录
在 Django ORM 中,咱们能够通过创立模型的实例来创立新的记录。以下是一个创立新的 Blog
记录的示例:
from myapp.models import Blog
# 创立新的 Blog 实例
blog = Blog(title='My first blog', content='This is my first blog post.')
blog.save() # don't forget to call save method
save()
办法会将新的 Blog
实例保留到数据库中。
读取记录
Django ORM 提供了多种办法来读取数据库中的记录。咱们能够应用 all()
办法获取所有记录,也能够应用 filter()
办法获取满足特定条件的记录。
from myapp.models import Blog
# 获取所有 Blog 记录
blogs = Blog.objects.all()
# 输入所有 Blog 的题目
for blog in blogs:
print(blog.title)
如果有一个名为 ”My first blog” 的博客,下面的代码将会输入:
My first blog
更新记录
更新数据库中的记录也很简略。咱们能够获取一个记录的实例,批改它的属性,而后调用 save()
办法:
from myapp.models import Blog
# 获取第一个 Blog 记录
blog = Blog.objects.first()
# 更新题目
blog.title = 'My updated blog'
blog.save()
这段代码将更新数据库中第一个博客的题目。
删除记录
要删除数据库中的记录,咱们能够获取一个记录的实例,而后调用 delete()
办法:
from myapp.models import Blog
# 获取第一个 Blog 记录
blog = Blog.objects.first()
# 删除记录
blog.delete()
这段代码将删除数据库中的第一个博客。
Django ORM 数据库进阶操作
在把握了 Django ORM 的根底操作后,接下来咱们来看看一些更高级的数据库操作,包含简单查问、查问优化等。
简单查问
在 Django ORM 中,咱们能够应用 filter()
、exclude()
、order_by()
等办法进行简单查问。
例如,咱们能够找到所有题目蕴含 ”django” 的博客,并依照公布日期降序排序:
from myapp.models import Blog
# 获取所有题目蕴含 'django' 的 Blog 记录,并依照公布日期降序排序
blogs = Blog.objects.filter(title__contains='django').order_by('-pub_date')
# 输入这些 Blog 的题目
for blog in blogs:
print(blog.title)
如果存在题目蕴含 ’django’ 的博客,上述代码将会依照公布日期的降序打印它们的题目。
查问优化
对于大型数据库,优化查问是十分重要的。Django ORM 提供了几种工具来帮忙你优化查问,包含 select_related()
和prefetch_related()
。
select_related()
能够一次性获取与查问对象有 ForeignKey 关联的对象,这能够缩小数据库查问次数:
from myapp.models import Blog
# 获取所有 Blog 记录,并一次性获取每个 Blog 的 author 信息
blogs = Blog.objects.select_related('author').all()
# 输入 Blog 的题目和作者名
for blog in blogs:
print(blog.title, blog.author.name)
如果有作者名为 ’John’ 且题目为 ”My first blog” 的博客,上述代码将会输入:
My first blog John
prefetch_related()
对于 ManyToMany 关联和一对多关联也十分有用,它能够一次性获取所有相干对象,缩小数据库查问次数。
利用数据库束缚保证数据一致性
Django ORM 提供了多种数据库束缚,如 unique
和check
等,能够帮忙咱们确保数据库的数据一致性。
# 例子:应用 unique 束缚确保每个作者的 email 是惟一的
class Author(models.Model):
name = models.CharField(max_length=100)
email = models.EmailField(unique=True)
应用批量操作晋升性能
Django ORM 提供了 bulk_create
和bulk_update
等办法,能够让咱们以更高效的形式进行批量创立和更新。
# 例子:应用 bulk_create 办法批量创建对象
authors = [Author(name=f'Author {i}') for i in range(1000)]
Author.objects.bulk_create(authors) # 这个操作只须要一次数据库查问
应用原生 SQL
只管 Django ORM 提供了许多弱小的查问工具,但有时候你可能须要间接执行 SQL 语句。Django ORM 容许你执行原生 SQL,你能够应用 raw()
办法或者 cursor()
办法来执行原生 SQL:
from django.db import connection
# 应用 cursor()执行原生 SQL
with connection.cursor() as cursor:
cursor.execute("SELECT title FROM myapp_blog")
row = cursor.fetchone()
print(row)
这段代码将间接执行 SQL 查问,并打印出第一个博客的题目。尽管 Django ORM 提供了.raw()办法容许咱们间接执行 SQL 查问,然而这个办法应该尽量避免应用,因为它可能会引发 SQL 注入等平安问题,同时也失去了 Django ORM 的许多长处。
Django 数据库迁徙
Django 的数据库迁徙零碎可能主动地将你对模型的更改(减少字段、删除模型等)转换为 SQL 命令,并在数据库中执行这些命令。这是一种对数据库进行版本控制的形式,让你可能更改你的模型并放弃数据库的更新。
创立迁徙
当你更改了你的模型(例如,增加一个字段、扭转一个字段的类型等),你须要创立一个迁徙来将这些更改利用到数据库。你能够应用 makemigrations
命令来创立迁徙:
python manage.py makemigrations your_app_name
上述命令将会查看你的模型与数据库的以后状态,而后创立一个新的迁徙,该迁徙蕴含了将数据库更新至新状态所需的所有操作。
利用迁徙
创立了迁徙之后,你须要应用 migrate
命令来利用这些更改到数据库:
python manage.py migrate
该命令将执行所有未利用的迁徙,将你的数据库更新至最新状态。
查看迁徙状态
你能够应用 showmigrations
命令查看所有迁徙的状态(已利用的和未利用的):
python manage.py showmigrations
执行上述命令将会列出所有的迁徙以及它们的状态,这能够帮忙你理解数据库的以后状态。
回滚迁徙
有时,你可能须要撤销某个迁徙。你能够应用 migrate
命令和迁徙名(或迁徙名之前的迁徙名)来回滚迁徙:
python manage.py migrate your_app_name 0001
该命令将会撤销名为 0002
的迁徙(以及在其之后的所有迁徙),并将数据库回滚至 0001
的状态。
Django ORM 的有余点
只管 Django ORM 是一个弱小且不便的工具,但它并不是无懈可击的。理解这些局限性能够帮忙咱们更加理智地决定何时以及如何应用它。
性能开销
Django ORM 须要额定的解决来将数据库的行转换为 Python 对象。这意味着应用 Django ORM 通常会比间接应用 SQL 语句慢一些。然而,这种性能开销通常是能够承受的,除非你正在解决极大量的数据。
不反对某些简单的 SQL 查问
尽管 Django ORM 反对许多 SQL 性能,但有一些简单的 SQL 查问可能无奈通过 Django ORM 的查问 API 来实现。例如,对于某些数据库的特定个性或高级 SQL 性能,可能须要写原生的 SQL 语句。
须要额定的学习和了解
尽管 Django ORM 能够帮忙咱们防止间接编写 SQL,然而要无效地应用它,依然须要了解数据库的基本概念。而且,Django ORM 本身的 API 和个性也须要一些学习和了解。
对数据库的暗藏可能导致误会
Django ORM 暗藏了数据库的许多细节,这使得编程变得更简略,但也可能导致开发者对正在执行的数据库操作有误会。例如,一个看似简略的操作可能实际上引发了屡次数据库查问。
# 例子:看似简略的操作实际上引发了屡次数据库查问
for book in Book.objects.all():
print(book.author.name) # 这个操作对每本书都会引发一个数据库查问
在这个例子中,打印每本书的作者名字的操作实际上对每本书都会引发一个数据库查问,如果有大量的书籍,那么这个操作将会十分慢。这是因为 Django ORM 默认是懒加载的,也就是说,它只在须要的时候才会去数据库查问数据。
Django ORM 总结与瞻望
通过这篇文章的学习,咱们深刻理解了 Django ORM 的工作原理,实现了一些根底和进阶的数据库操作,同时也理解了它的一些最佳实际和局限性。
Django ORM 作为 Python Web 开发中的一个重要局部,它以其简洁和弱小的性能博得了许多开发者的青睐。只管它有一些局限性,比方某些简单查问的反对不是很好,以及它对数据库操作的暗藏可能会导致性能问题,然而总体来说,Django ORM 是一个十分无效的工具,能够帮忙咱们更快更好地进行 Web 开发。
在将来,咱们能够期待 Django ORM 将会继续改良,提供更多的性能和更好的性能。同时,咱们也能够通过深刻学习和实际,更好地利用 Django ORM,进步咱们的开发效率。
如有帮忙,请多关注
集体微信公众号:【Python 全视角】
TeahLead_KrisChang,10+ 年的互联网和人工智能从业教训,10 年 + 技术和业务团队治理教训,同济软件工程本科,复旦工程治理硕士,阿里云认证云服务资深架构师,上亿营收 AI 产品业务负责人。