Docs Menu
Docs Home
/ /
/ / /

Transacciones y Sesiones

En esta guía, aprenderá a usar Django MongoDB Backend para realizar transacciones. Las transacciones permiten ejecutar una serie de operaciones que modifican los datos solo si se confirma la transacción completa. Si alguna operación de la transacción no se realiza correctamente, Django MongoDB Backend la detiene y descarta todos los cambios en los datos antes de que sean visibles. Esta característica se denomina atomicidad.

En MongoDB, las transacciones se ejecutan dentro de sesiones lógicas. Una sesión es una agrupación de operaciones de lectura o escritura relacionadas que se ejecutan secuencialmente. Las sesiones permiten la consistencia causal de un grupo de operaciones y ejecutarlas en una transacción compatible con ACID, que cumple con los requisitos de atomicidad, consistencia, aislamiento y durabilidad.

La API de transacciones nativa de Django no es compatible, pero Django MongoDB Backend ofrece una API de transacciones personalizada que habilita la misma funcionalidad. Para ejecutar operaciones dentro de una transacción, defínalas dentro de un bloque de código atómico. Django MongoDB Backend gestiona la lógica de la sesión internamente, por lo que no es necesario iniciar una sesión manualmente antes de ejecutar una transacción.

Importante

Limitaciones de las transacciones

La API de transacciones del backend de Django MongoDB tiene varias limitaciones. Para ver una lista de limitaciones, consulte Compatibilidad de bases de datos y colecciones en la guía de compatibilidad de funciones de Django y MongoDB.

Los ejemplos de esta guía utilizan el Movie modelo, que representa la colección sample_mflix.movies de la Conjuntos de datos de muestra de Atlas. La Movie clase de modelo tiene la siguiente definición:

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

El Movie modelo incluye una Meta clase interna, que especifica los metadatos del modelo, y un __str__() método, que define la representación de cadena del modelo. Para obtener más información sobre estas características del modelo,consulte "Definir un modelo" en la guía "Crear modelos".

Puedes usar el shell interactivo de Python para ejecutar los ejemplos de código. Para acceder al shell, ejecuta el siguiente comando desde el directorio raíz de tu proyecto:

python manage.py shell

Después de ingresar al shell de Python, asegúrese de importar los siguientes modelos y módulos:

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

Para aprender a crear una aplicación Django que use el Movie modelo y el shell interactivo de Python para interactuar con documentos MongoDB, visita el tutorial Primeros pasos.

Para iniciar una transacción de base de datos, llame a la función django_mongodb_backend.transaction.atomic(). Puede usar esta función como decorador o gestor de contexto.

Asegúrese de importar el módulo transaction mediante la siguiente declaración de importación:

from django_mongodb_backend import transaction

Puede iniciar una transacción de base de datos añadiendo el decorador @transaction.atomic encima de su función. Este decorador garantiza la atomicidad de cualquier operación de base de datos dentro de la función. Si la función se completa correctamente, los cambios se confirman en MongoDB.

El siguiente ejemplo llama al método create() dentro de una transacción, que inserta un documento en la colección sample_mflix.movies si la transacción tiene éxito:

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

Como alternativa, puede usar el administrador de contexto transaction.atomic() para crear un bloque de código atómico. Este ejemplo ejecuta la misma operación que el ejemplo anterior, pero usa un administrador de contexto para iniciar una transacción:

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

Para realizar ciertas acciones solo si una transacción se completa correctamente, puede usar la función transaction.on_commit(). Esta función permite registrar devoluciones de llamada que se ejecutan después de confirmar una transacción en la base de datos. Pase una función, o cualquier objeto invocable, como argumento a on_commit().

El siguiente ejemplo busca películas que tengan un valor genre de ["Horror", "Comedy"] solo después de que se complete una transacción de base de datos relacionada:

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)

Para gestionar las excepciones que ocurren durante una transacción, agrega lógica de manejo de errores alrededor de tu bloque de código atómico. Si decides gestionar los errores dentro del bloque atómico, podrías ocultar esos errores a Django. Puesto que Django utiliza errores para determinar si se debe confirmar o revertir una transacción, esto puede causar un comportamiento inesperado.

Si una transacción no se completa correctamente, Django no revierte los cambios realizados en los campos de un modelo. Para evitar inconsistencias entre los modelos y los documentos de la base de datos, es posible que deba restaurar manualmente los valores originales de los campos.

El siguiente ejemplo incluye lógica de manejo de errores que revierte el valor title modificado del documento recuperado si falla la transacción de la base de datos:

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()

Dado que el código realiza una segunda operación de base de datos basada en el valor title del modelo, revertir el cambio si la transacción falla evita más inconsistencias en los datos.

Para obtener más información sobre la API de transacciones de Django, consulte Transacciones de base de datos en la documentación de Django.

Volver

Búsqueda vectorial de MongoDB

En esta página