Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /
/ / /

Transacciones y Sesiones

En esta guía, puedes aprender cómo usar Django MongoDB Backend para realizar transacciones. Las transacciones permiten ejecutar una serie de operaciones que cambian los datos solo si toda la transacción se confirma. Si alguna operación en la transacción no tiene éxito, Django MongoDB Backend detiene la transacción y descarta todos los cambios en los datos antes de que se vuelvan visibles. Esta funcionalidad se llama atomicidad.

En MongoDB, las transacciones se ejecutan dentro de sesiones lógicas. Una sesión es un grupo de operaciones de lectura o escritura relacionadas que deseas ejecutar de manera secuencial. Las sesiones permiten una coherencia causal para un grupo de operaciones y permiten ejecutar operaciones en una transacción compatible con ACID , que es una transacción que cumple con la expectativa de atomicidad, coherencia, 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 transacción

La API de transacciones de Django MongoDB Backend 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 clase de modelo Movie 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 la shell interactiva de Python para ejecutar los ejemplos de código. Para ingresar a la shell, ejecute el siguiente comando desde el directorio raíz de su 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 de Django que use el modelo Movie y el shell interactivo de Python para interactuar con documentos de MongoDB, visita el tutorial de Introducción a Django MongoDB Backend.

Para iniciar una transacción de base de datos, llama a la función django_mongodb_backend.transaction.atomic(). Puedes usar esta función como decorador o como 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, lo 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 con éxito, puedes utilizar la función transaction.on_commit(). Esta función te permite registrar callbacks que se ejecutan después de que una transacción se haya recopilado en la base de datos. Pasa una función, o cualquier objeto invocable, como argumento a on_commit().

El siguiente ejemplo query películas que tienen un valor de genre de ["Horror", "Comedy"] sólo 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 una lógica de manejo de errores que revierte el valor modificado de title del documento recuperado si la transacción de base de datos falla:

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 en la base de datos según el valor title del modelo, revertir el cambio si la transacción falla previene inconsistencias de datos adicionales.

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

Volver

Búsqueda vectorial de MongoDB

En esta página