Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

548
Visualizações
¿Cuál es el caso de uso para on_commit de Django?

Leyendo esta documentación https://docs.djangoproject.com/en/4.0/topics/db/transactions/#django.db.transaction.on_commit

Este es el caso de uso para on_commit

 with transaction.atomic(): # Outer atomic, start a new transaction transaction.on_commit(foo) # Do things... with transaction.atomic(): # Inner atomic block, create a savepoint transaction.on_commit(bar) # Do more things... # foo() and then bar() will be called when leaving the outermost block

Pero, ¿por qué no simplemente escribir el código como de costumbre sin ganchos on_commit ? Me gusta esto:

 with transaction.atomic(): # Outer atomic, start a new transaction # Do things... with transaction.atomic(): # Inner atomic block, create a savepoint # Do more things... foo() bar() # foo() and then bar() will be called when leaving the outermost block

Es más fácil de leer ya que no requiere más conocimiento de las API de Django y las declaraciones se ponen en el orden en que se ejecutan. Es más fácil de probar ya que no tienes que usar ninguna clase de prueba especial para Django.

Entonces, ¿cuál es el caso de uso para el gancho on_commit ?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

Documentación de Django:

Django proporciona la función on_commit() para registrar funciones de devolución de llamada que deben ejecutarse después de que una transacción se confirme con éxito

Es el propósito principal. Una transacción es una unidad de trabajo que desea tratar atómicamente. O sucede completamente o no sucede en absoluto. Lo mismo se aplica a su código. Si algo salió mal durante las operaciones de la base de datos, es posible que no necesite hacer algunas cosas.

Consideremos un flujo de lógica empresarial:

  1. El usuario envía sus datos de registro a nuestro punto final, lo validamos, etc.
  2. Guardamos el nuevo usuario en nuestra base de datos.
  3. Le enviamos una carta de "hola" al correo electrónico con un enlace para confirmar su cuenta.

Si algo sale mal durante el paso 2, no deberíamos ir al paso 3.

Podemos pensar que, bueno, obtendré una excepción y no ejecutaré ese código también. ¿Por qué todavía lo necesitamos?

A veces, realiza acciones en su código en función de la suposición de que la transacción es exitosa antes de las operaciones de base de datos potencialmente peligrosas. Por ejemplo, primero desea verificar si puede enviar un correo electrónico a su usuario, porque sabe que su tercero de correo electrónico a menudo le otorga 500. En ese caso, desea recaudar 500 para el usuario y pedirle que se registre más tarde. (una muy mala idea, por cierto, pero es solo un ejemplo sintético).

Cuando su función (por ejemplo, con el decorador @atomic ) contiene muchas operaciones de base de datos, seguramente no querrá memorizar todos los estados de las variables para usarlas después de todo el código relacionado con la base de datos. Me gusta esto:

  • Validación del pedido del usuario.
  • Comprobando en DB si se pudo completar.
  • Si es posible, debemos enviar una solicitud al CRM de terceros con los detalles del pedido.
  • Si no pudiera, entonces deberíamos crear un ticket de soporte en otro tercero.
  • Guardando el pedido del usuario en la base de datos, actualizando el modelo del usuario.
  • Envío de una notificación de mensajería al empleado responsable del pedido.
  • Guardando información, esa notificación para el empleado se envió con éxito a la base de datos.

Puedes imaginarte el lío que tendríamos si no nos on_commit en esta situación y tuviéramos un gran try-catch esto.

over 4 years ago · Santiago Trujillo Relatório

0

El código de ejemplo proporcionado en los documentos de Django es transaction.on_commit(lambda: some_celery_task.delay('arg1')) y probablemente se deba específicamente a que esto surge mucho con las tareas de apio.

Imagínese si hace lo siguiente dentro de una transacción:

 my_object = MyObject.objects.create() some_celery_task.delay(my_object.pk)

Luego, en su tarea de apio, intente hacer esto:

 @app.task def some_celery_task(object_pk) my_object = MyObject.objects.get(pk=object_pk)

Esto puede funcionar la mayor parte del tiempo, pero al azar obtendrá errores en los que no puede encontrar el objeto (dependiendo de qué tan rápido se ejecute la tarea de trabajo porque es una condición de carrera). Esto se debe a que creó un registro MyObject dentro de una transacción, pero en realidad no está disponible en la base de datos hasta que se ejecuta COMMIT . Celery no tiene acceso a esa transacción abierta, por lo que debe ejecutarse después de COMMIT . También existe la posibilidad muy real de que algo más tarde provoque un ROLLBACK y esa tarea de apio nunca se deba llamar.

Entonces... Tienes que hacer:

 my_object = MyObject.objects.create() transaction.on_commit(lambda: some_celery_task.delay(my_object.pk))

Ahora, la tarea de apio no se llamará hasta MyObject se haya guardado en la base de datos después de llamar a COMMIT .

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda