Skip to content

Django ORM 详解:轻松掌握数据增加的多种方法 (save, create, bulk_create 及关联操作)

Django 框架以其强大的对象关系映射(Object-Relational Mapper, ORM)系统而闻名,它允许开发者使用 Python 代码与数据库进行交互,而无需直接编写 SQL 语句。掌握 ORM 的基本操作是高效开发 Django 应用的基础,其中,向数据库中增加新数据是最常见的需求之一。本文将深入探讨 Django ORM 中用于增加数据的几种核心方法:save()create() 以及用于批量操作的 bulk_create(),并特别说明如何处理包含外键(Foreign Key)关联的数据记录。

使用 save() 方法增加数据

save() 方法是 Django 模型实例上的一个基础方法,用于将对象的状态持久化到数据库。当需要创建一个新的数据记录时,通常的流程是先实例化一个模型对象,为其属性赋予相应的值,然后调用该实例的 save() 方法。

假设存在一个简单的 Book 模型,用于存储书籍信息:

python
# models.py
from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)
    author_name = models.CharField(max_length=50)
    published_date = models.DateField()

    def __str__(self):
        return self.title

要使用 save() 方法添加一本新书,可以执行以下操作:

python
# views.py or Python shell
from .models import Book
from datetime import date

# 1. 创建模型实例
new_book = Book()

# 2. 设置实例属性
new_book.title = "深入理解计算机系统"
new_book.author_name = "Randal E. Bryant"
new_book.published_date = date(2016, 11, 28) # 假设出版日期

# 3. 调用 save() 方法将数据存入数据库
new_book.save()

# new_book 对象现在拥有了数据库分配的主键 id (如果模型有自增主键)
print(f"新书已添加,ID 为: {new_book.id}")

这种方式非常直观,将对象的创建和保存过程清晰地分离开来。值得注意的是,save() 方法不仅用于创建新记录,当对一个已经从数据库中获取的模型实例进行修改后,再次调用 save() 会执行更新(UPDATE)操作。但在此处,我们关注的是其创建新记录的功能。

使用 create() 方法增加数据

相较于 save() 方法需要先实例化再保存的两步操作,Django 的模型管理器(Model Manager,通常通过 Model.objects 访问)提供了一个更为便捷的 create() 方法。这个方法允许开发者在一行代码中同时完成模型实例的创建和数据库保存。

继续使用上面的 Book 模型,使用 create() 方法添加新书的代码如下:

python
# views.py or Python shell
from .models import Book
from datetime import date

# 使用 create() 方法一步到位
another_book = Book.objects.create(
    title="代码整洁之道",
    author_name="Robert C. Martin",
    published_date=date(2008, 8, 1) # 假设出版日期
)

print(f"另一本新书已添加,ID 为: {another_book.id}")

create() 方法直接接收模型的字段名作为关键字参数,并在内部完成对象的实例化和 save() 调用。这种方式代码更简洁,尤其适用于简单的数据添加场景。它与先实例化再调用 save() 的效果是等价的,都实现了向数据库插入一条新记录。选择哪种方法取决于具体的编码习惯和场景需求,create() 因其简洁性而广受欢迎。

批量增加数据 (bulk_create())

当需要一次性向数据库中插入大量数据时,逐条调用 save()create() 会导致频繁的数据库交互,性能较低。为了解决这个问题,Django ORM 提供了 bulk_create() 方法,它允许将多个模型实例一次性插入数据库,通常只需要执行一条 SQL 语句(具体取决于数据库后端和对象数量),从而显著提高效率。

使用 bulk_create() 的基本步骤是先创建好一个包含多个待插入模型实例的列表,然后将该列表传递给 bulk_create() 方法。

python
# views.py or Python shell
from .models import Book
from datetime import date

books_to_create = [
    Book(title="算法导论", author_name="Thomas H. Cormen", published_date=date(2009, 7, 31)),
    Book(title="设计模式", author_name="Erich Gamma", published_date=date(1994, 10, 21)),
    Book(title="Effective Python", author_name="Brett Slatkin", published_date=date(2019, 11, 15))
]

# 调用 bulk_create() 批量插入
Book.objects.bulk_create(books_to_create)

print(f"已批量添加 {len(books_to_create)} 本书。")

需要注意的是,bulk_create() 为了性能牺牲了一些特性。它通常不会调用每个模型实例的 save() 方法,因此模型的自定义 save() 逻辑不会被执行,也不会发送 pre_savepost_save 信号。此外,在某些数据库后端(如旧版 PostgreSQL 或 MySQL),bulk_create() 可能无法像 save()create() 那样自动设置对象的主键(id)属性。尽管有这些限制,但在需要高性能批量插入的场景下,bulk_create() 是非常有价值的工具。

增加关联 Key 数据(外键 Foreign Key)

在实际应用中,数据模型之间常常存在关联关系,最常见的就是外键(Foreign Key)。例如,一个 Article 模型可能关联到一个 Author 模型。

python
# models.py
from django.db import models

class Author(models.Model):
    name = models.CharField(max_length=50)

    def __str__(self):
        return self.name

class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='articles') # 外键关联

    def __str__(self):
        return self.title

下图展示了 AuthorArticle 之间的一对多关系:

当需要创建一篇新文章并指定其作者时,处理外键字段是关键。有两种主要方式来设置外键关联:

方法一:传递关联对象实例

这是最推荐也是最符合 ORM 思想的方式。首先获取或创建一个关联对象(例如 Author 的实例),然后在创建 Article 实例时,将这个 Author 实例直接赋值给 Articleauthor 字段。

使用 save() 方法:

python
# views.py or Python shell
from .models import Author, Article

# 假设作者已存在,先获取作者实例
try:
    author_instance = Author.objects.get(name="张三")
except Author.DoesNotExist:
    # 如果作者不存在,可以先创建
    author_instance = Author.objects.create(name="张三")

# 创建 Article 实例并设置外键
new_article = Article()
new_article.title = "Django ORM 基础"
new_article.content = "这是一篇关于 Django ORM 的入门文章..."
new_article.author = author_instance # 直接将 Author 实例赋给外键字段

# 保存 Article 实例
new_article.save()

print(f"文章 '{new_article.title}' 已添加,作者为 {new_article.author.name}")

使用 create() 方法:

python
# views.py or Python shell
from .models import Author, Article

# 同样先获取或创建作者实例
author_instance = Author.objects.get_or_create(name="李四")[0] # get_or_create 返回 (object, created) 元组

# 在 create() 方法中直接传递 author 实例
another_article = Article.objects.create(
    title="Python 异步编程",
    content="深入探讨 asyncio...",
    author=author_instance # 传递 Author 实例
)

print(f"文章 '{another_article.title}' 已添加,作者为 {another_article.author.name}")

通过传递完整的关联对象实例,代码意图清晰,并且利用了 Django ORM 的类型检查和关系处理能力。

方法二:传递关联对象的主键 ID

Django ORM 也允许直接使用关联对象的主键 ID 来设置外键关系。在幕后,外键字段实际存储的是关联表的主键值。因此,可以直接将 Author 对象的主键 ID 赋值给 Article 模型的 author_id 字段(Django 会自动为外键字段 author 创建一个名为 author_id 的数据库列)。

使用 save() 方法:

python
# views.py or Python shell
from .models import Author, Article

# 假设已知作者 ID 为 1
author_id_value = 1

article_using_id = Article()
article_using_id.title = "数据库设计原则"
article_using_id.content = "关于数据库范式和反范式..."
article_using_id.author_id = author_id_value # 直接设置外键 ID

article_using_id.save()

# 注意:此时访问 article_using_id.author 会触发一次数据库查询来获取关联的 Author 对象
print(f"文章 '{article_using_id.title}' 已添加,作者 ID 为 {article_using_id.author_id}")

使用 create() 方法:

python
# views.py or Python shell
from .models import Author, Article

# 假设已知作者 ID 为 2
author_id_value = 2

article_created_with_id = Article.objects.create(
    title="RESTful API 设计",
    content="探讨 REST 架构风格的最佳实践...",
    author_id=author_id_value # 在 create() 中传递外键 ID
)

print(f"文章 '{article_created_with_id.title}' 已添加,作者 ID 为 {article_created_with_id.author_id}")

虽然直接使用 ID 也可以工作,并且在某些特定场景下(例如,只知道 ID 而不想额外查询获取对象实例)可能更直接,但通常不如传递对象实例那样清晰和安全。传递对象实例可以更好地利用 ORM 提供的抽象,减少直接操作数据库 ID 的需要。

小结

本文介绍了 Django ORM 中增加数据的几种主要方法。save() 方法提供了基础的对象保存机制,适用于先构建对象再持久化的场景。create() 方法作为模型管理器的便捷函数,能够一步完成对象的创建和保存,代码更为简洁。当需要高效插入大量数据时,bulk_create() 是性能优化的利器,尽管有一些使用上的限制。最后,对于包含外键关联的数据,推荐通过传递关联对象实例的方式来设置关系,这使得代码更具可读性并充分利用了 ORM 的优势,当然,直接使用关联对象的主键 ID 也是一种可行的方式。熟练掌握这些数据增加技术,将有助于开发者更高效地构建功能丰富的 Django 应用。

参考资料