`ManyRelatedManager.add()` doesn't commit to database
|Reported by:||Tai Lee||Owned by:||nobody|
|Component:||Database layer (models, ORM)||Version:||master|
|Severity:||Release blocker||Keywords:||add reverse m2m relation not committed|
|Has patch:||no||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
Execute the following in order in two different interactive shells (two processes) to trigger the bug. The problem is that the call to
.add() is not committed to the database until a second call to
.create(). If the first process happens to be a management command (for example) and there are no subsequent database writes, the relations are never committed. You can also confirm this by inspecting the database after executing each command.
# shell 1 >>> from django.contrib.auth.models import * >>> u = User.objects.create(username='test') >>> u.groups.add(Group.objects.latest('pk')) >>> User.objects.get(username='test').groups.all() [<Group: motivate | members>] # shell 2 >>> from django.contrib.auth.models import * >>> User.objects.get(username='test').groups.all()  # shell 1 >>> u2 = User.objects.create(username='test2') # shell 2 >>> User.objects.get(username='test').groups.all() [<Group: motivate | members>] # sql command to check if group has been linked to user select * from auth_user_groups where user_id = (select id from auth_user where username = 'test');
I've tested this against trunk, and it was confirmed by ptone who also confirmed that it is a regression from 1.3. I tested on PostgreSQL and SQLite.
I'm not sure how to create an automated test for this, because the problem only exhibits when reading from the database from a different process or transaction.
Change History (4)
comment:1 Changed 5 years ago by
|Patch needs improvement:||unset|
|Triage Stage:||Unreviewed → Accepted|