sell.net_cost = sell_positions.aggregate(sum_net_cost=Sum(‘net_cost’))[‘sum_net_cost’]
logging.warning(f"SELL NET COST {sell.id} net_cost={sell.net_cost}“)
sell.save()
sell.refresh_from_db()
logging.warning(f"RESAVE SELL NET COST {sell.id} net_cost={sell.net_cost}”)
sell positions’ aggregate result is not 0 (I have checked many times with different logs)
I tried save(update_fields=[‘net_cost’]) and it didn’t help
I printed sell_positions.aggregate(sum_net_cost=Sum(‘net_cost’))[‘sum_net_cost’] before assigning to field, printed it after assigning, printed field’s value before saving (0) and after saving (it’s greater than 0, checked it both with update fields and without)
I tried to do it with and without transaction
I have no idea why it happens and my db value is 0 (IMPORTANT, it happens randomly)
all services (including db, are stable)
if I run the same code manually it works fine, but when I run it inside celery it fails sometimes. All tasks’ status = SUCCESS (I added logs for exceptions and failures)
There’s no overrided save method or signals
Feel free to ask for more information. Thank you in advance
with transaction.atomic():
logging.warning(f"sell={sell.id} setting net cost {sell_net_cost} {sell}") # here sell_net_cost is greater than zero
sell: Sell = Sell.objects.select_for_update().get(id=sell.id) # last attempt to fix
sell.net_cost = sell_net_cost
sell.save(update_fields=["net_cost"])
logging.warning(f"sell={sell.id} SAVED {sell.net_cost}") # here im getting non-zero value
sell.refresh_from_db()
logging.warning(f"sell={sell.id} SAVED {sell.net_cost} and after refresh") # here im also getting non-zero value
This code is all inside a transaction. You have to move the two last line outside the atomic block to make that run outside and thus be sure it was in fact saved to the db.
I’ve just tried it on my production, removed refresh_from_db() and printing log with new object’s data from transaction scope. And im getting the same result, logs are ok, db is full of zeroes
We may need to see more details about your runtime environment.
What database engine are you using?
What version of Django and Python?
What version of database engine are you using?
The reason I’m asking this is because I cannot currently replicate the results you are reporting here in my test environment.
Given this model:
class Sell(models.Model):
net_cost = models.DecimalField(max_digits=32, decimal_places=14)
def __str__(self):
return f"{self.id}"
With this view:
def update_sell(request, pk):
with transaction.atomic():
sell = Sell.objects.select_for_update().get(id=pk)
print(f'net cost = {sell.net_cost}')
sell.net_cost = 10
print(f'post-update net cost = {sell.net_cost}')
sell.save(update_fields=['net_cost'])
print(f'post-save net cost = {sell.net_cost}')
sell.refresh_from_db()
print(f'post-refresh net cost = {sell.net_cost}')
sell.refresh_from_db()
print(f'post-transaction net cost = {sell.net_cost}')
return HttpResponse(f'post-transaction net cost = {sell.net_cost}')
And initializing an instance of Sell: Sell.objects.create(net_cost=15).save()
And calling the view from the browser, I get the following response: post-transaction net cost = 10.00000000000000
with the following entries in my server log:
net cost = 15.00000000000000
post-update net cost = 10
post-save net cost = 10
post-refresh net cost = 10.00000000000000
post-transaction net cost = 10.00000000000000
127.0.0.1 - - [21/Feb/2025 09:51:23] "GET /st/us/1 HTTP/1.1" 200 -
Therefore, my current conjecture is that either the issue is somehow related to the environment or to some code that is not currently being shown.
Side note: This is with Python 3.12.8, Django 5.1.6, running under Werkzeug 3.0.6 (using runserver_plus) with psycopg2-binary 2.9.10 connecting to a Postgres 15.1 instance, all running on an Ubuntu 22.04 instance inside WSL 2 on Windows 11.
At this point I would check if there are nested atomic() blocks, if there are any raw except: blocks or similar that can swallow errors, and stuff like that.