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 nativa de transacciones de Django no es compatible, pero Django MongoDB Backend proporciona una API personalizada de transacciones que permite la misma funcionalidad. Para ejecutar operaciones dentro de una transacción, defínalas dentro de un bloque atómico de código. El Backend de Django MongoDB gestiona la lógica de la sesión internamente, por lo que no es necesario iniciar manualmente una sesión 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 Soporte de base de datos y colección 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 modelo Movie incluye una clase interna Meta, que especifica los metadatos del modelo, y un método __str__(), que define la representación en string del modelo. Para aprender sobre estas funcionalidades del modelo, consulta 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úrate de importar el módulo transaction utilizando la siguiente instrucción de importación:

from django_mongodb_backend import transaction

Puedes iniciar una transacción de base de datos agregando el decorador @transaction.atomic encima de la 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 con éxito, 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"]
)

Alternativamente, puedes usar el gestor de contexto transaction.atomic() para crear un bloque atómico de código. Este ejemplo ejecuta la misma operación que el ejemplo anterior, pero utiliza 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 tiene éxito, Django no revierte los cambios realizados en los campos de un modelo. Para evitar inconsistencias entre tus modelos y los documentos de la base de datos, podrías necesitar 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