Actualizar un contador en un modelo en Django
A veces necesitamos realizar algún tipo de operación aritmética sencilla en el modelo, y queremos que persista en la base de datos. Un ejemplo común es un contador, que queremos incrementar o decrementar en determinadas circunstancias.
Una solución sencilla sería hacerlo directamente en Python, algo como esto:
product = Item.objects.get(pk=4523) product.stock += 1 product.save()
Funciona perfecto, pero tiene dos problemas: Uno es una posible condición de carrera, si tenemos la mala suerte de que otro proceso está cambiando el valor del contador stock
justo durante el intervalo entre que hemos leído los datos de la base de datos y el momento es que volvemos a salvarlos.
El segundo problema es otro aspecto del mismo, estamos haciendo dos consultas a la base de datos, una para obtener el valor antiguo y otra para guardar el valor nuevo.
Podemos resolver ambos problemas (Ya que los dos tienen la misma base) con un único paso, que realizará de forma atómica la propia base de datos, usando lo que Django llama expresiones F. Las expresiones F nos permiten realizar una actualización de un campo con valores relativos otros campos de la tabla.
Para el ejemplo anterior, la solución mejorada podría ser:
from django.db.models import F product = Item.objects.get(pk=4523) Item.stock = F("stock”) + 1 product.save(update_fields=['stock'])
El resultado sería una única interacción con la base de datos, que ejecutaría un código SQL similar al siguiente :
UPDATE Item SET stock = stock + 1 WHERE id = 4523;
Añadir un comentario