Join us Sept 17 at .local NYC! Use code WEB50 to save 50% on tickets. Learn more >
MongoDB Event
Docs 菜单
Docs 主页
/ / /
Django MongoDB后端
/

事务和会话

在本指南中,您可以学习;了解如何使用 Django MongoDB 后端来执行事务。事务允许您运行一系列仅在提交整个ACID 事务后才更改数据的操作。如果ACID 事务中的任何操作不成功,Django MongoDB后端会停止ACID 事务,并在数据更改变得可见之前丢弃所有更改。此功能称为原子性

在MongoDB中,事务在逻辑会话中运行。会话是要按顺序运行的一组相关读取或写入操作。会话启用为一群组操作启用因果一致性,并允许您在符合ACID的ACID 事务中运行操作,该ACID 事务满足原子性、一致性、隔离性和持久性的预期。

不支持 Django 的原生ACID 事务API ,但 Django MongoDB后端提供了可实现相同功能的自定义ACID 事务API 。要在ACID 事务中运行操作,请在原子代码区块中定义这些操作。Django MongoDB后端在内部管理会话逻辑,因此您无需在运行ACID 事务之前手动启动会话。

重要

事务限制

Django MongoDB后端的ACID 事务API有一些限制。要查看限制列表,请参阅 Django 和MongoDB功能兼容性指南中的 数据库和集合支持

本指南中的示例使用 Movie 模型,该模型表示 Atlas示例数据集中的 sample_mflix.movies集合。Movie 模型类具有以下定义:

from django.db import models
from django_mongodb_backend.fields import ArrayField
class Movie(models.Model):
title = models.CharField(max_length=200)
plot = models.TextField(blank=True)
runtime = models.IntegerField(default=0)
released = models.DateTimeField("release date", null=True, blank=True)
genres = ArrayField(models.CharField(max_length=100), null=True, blank=True)
class Meta:
db_table = "movies"
managed = False
def __str__(self):
return self.title

Movie 模型包括一个内部 Meta 类(用于指定模型元数据)和一个 __str__() 方法(用于定义模型的字符串表示形式)。 要学习;了解这些模型功能,请参阅创建模型指南中的定义模型。

您可以使用Python交互式Shell来运行代码示例。 要进入Shell ,请从项目的根目录运行以下命令:

python manage.py shell

进入Python Shell后,请确保导入以下模型和模块:

from <your application name>.models import Movie
from django.utils import timezone
from datetime import datetime

要学习;了解如何创建使用 Movie 模型和Python交互式Shell与MongoDB文档交互的Django应用程序,请访问入门教程

要启动数据库ACID 事务,请调用 django_mongodb_backend.transaction.atomic() 函数。您可以将此函数用作装饰器或上下文管理器。

确保使用以下导入声明导入 transaction 模块:

from django_mongodb_backend import transaction

您可以通过在函数上方添加 @transaction.atomic 装饰器来启动数据库ACID 事务。此装饰器ACID 一致性保证函数内任何数据库操作的原子性。如果函数成功完成,则将更改提交到MongoDB。

以下示例在ACID 事务中调用 create() 方法,如果ACID 事务成功,该方法会将文档插入 sample_mflix.movies集合:

@transaction.atomic
def insert_movie_transaction():
Movie.objects.create(
title="Poor Things",
runtime=141,
genres=["Comedy", "Romance"]
)

或者,您可以使用 transaction.atomic() 上下文管理器创建原子代码区块。此示例运行与前面的示例相同的操作,但使用上下文管理器来启动ACID 事务:

def insert_movie_transaction():
with transaction.atomic():
Movie.objects.create(
title="Poor Things",
runtime=141,
genres=["Comedy", "Romance"]
)

要仅在ACID 事务成功完成时才执行某些操作,可以使用 transaction.on_commit() 函数。此函数允许您注册在ACID 事务提交到数据库后运行的回调。将函数或任何可调用对象作为参数传递给 on_commit()

以下示例仅在相关数据库ACID 事务完成后查询 genre 值为 ["Horror", "Comedy"] 的电影:

def get_horror_comedies():
movies = Movie.objects.filter(genres=["Horror", "Comedy"])
for m in movies:
print(f"Title: {m.title}, runtime: {m.runtime}")
def insert_movie_with_callback():
with transaction.atomic():
Movie.objects.create(
title="The Substance",
runtime=140,
genres=["Horror", "Comedy"]
)
transaction.on_commit(get_horror_comedies)

要处理ACID 事务期间发生的异常,请在原子代码区块周围添加错误处理逻辑。如果在原子区块内处理错误,则可能会在 Django 中掩盖这些错误。由于 Django 使用错误来确定是提交还是回滚ACID 事务,因此这可能会导致意外行为。

如果ACID 事务不成功,Django 不会恢复对模型字段所做的任何更改。为了避免模型和数据库文档之间出现不一致,您可能需要手动恢复原始字段值。

以下示例包含错误处理逻辑,该逻辑在数据库ACID 事务失败时恢复检索到的文档的修改后的 title 值:

movie = Movie.objects.get(title="Jurassic Park")
movie.title = "Jurassic Park I"
try:
with transaction.atomic():
movie.save()
except DatabaseError:
movie.title = "Jurassic Park"
if movie.title == "Jurassic Park I":
movie.plot = "An industrialist invites experts to visit his theme park of cloned dinosaurs. After a power failure," \
" the creatures run loose, putting everyone's lives, including his grandchildren's, in danger."
movie.save()

由于代码根据模型的 title 值执行第二个数据库操作,因此在ACID 事务错误时恢复更改可以防止进一步的数据不一致。

要学习;了解有关 DjangoACID 事务API 的更多信息,请参阅 Django 文档中的数据库事务。

后退

Atlas Vector Search

在此页面上