Django saves but it doesn't appear in db

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}”)

  1. sell positions’ aggregate result is not 0 (I have checked many times with different logs)
  2. I tried save(update_fields=[‘net_cost’]) and it didn’t help
  3. 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)
  4. I tried to do it with and without transaction
  5. I have no idea why it happens and my db value is 0 (IMPORTANT, it happens randomly)
  6. all services (including db, are stable)
  7. 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

Welcome @DooDleZ !

I think to be able to diagnose this, we’re going to need to see the models involved and the full view function in which this process appears.

It would also be helpful if you could show a minimal sample of data that causes this to happen.

Hi! Should I add all the things in replies or edit my question?

Adding them to the replies is good.

class Sell(models.Model):
    net_cost = models.DecimalField(max_digits=32, decimal_places=14)
 
    def __str__(self):
        return f"{self.id}"



class SellPosition(models.Model):
    sell = models.ForeignKey(to=Sell, on_delete=models.CASCADE, related_name='positions')
    net_cost = models.DecimalField(max_digits=32, decimal_places=14)

my code here:

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

but after all I see 0 value in my db

Where does sell_net_cost come from? I don’t see where it’s defined in this block.

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 didn’t add other code, but let assume it’s just some number (like sell_net_cost = 10)

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.

Hi, thank you for helping!

I also can’t get why it happens because some of net costs are absolutely fine. I thought about a load, but not sure. Im using:

Django==4.2.9
psycopg2-binary==2.9.9

server: Ubuntu
Description: Ubuntu 24.04.1 LTS
Release: 24.04
Codename: noble

db engine - PostgreSQL inside docker container (image: postgres:13-alpine)
no special settings except shm_size: 1gb

im running django via gunicorn

I dont think that providing more code makes easier to reproduce the bug, because some of Sells are fine with the same code and the same logs

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.

nope, no hidden nested atomic blocks except I have showed above, the same with except