Opened 8 years ago
Closed 8 years ago
#28732 closed Bug (duplicate)
Deleted OneToOneRelation still referenced (not None) after refresh_from_db
| Reported by: | JeroenPeterBos | Owned by: | nobody |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 1.9 |
| Severity: | Normal | Keywords: | Refresh Database Object Delete |
| Cc: | jeroenbosleusden2@… | Triage Stage: | Unreviewed |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Issue:
I ran into the following problem. I have a test that will retrieve an account which has a relation to ActivationCode. In the test i call a function that recieves a string with which it can find the activationcode, after that the funciton will call delete on the ActivationCode. Now the problem is, when i call refresh_from_db() on the account it will say that account still has a related Activation Code ( while it obviously hasn't ) and the problem is proved when i call on this related ActivationCode, because a DoesNotExist exception will be thrown.
In my oppinion also this deleted relation object should be reflected in account when refreshing it.
Below is the relevant code
Models
class Account(models.Model):
user = models.OneToOneField(User)
activated = models.BooleanField(default=False)
class ActivationCode(models.Model):
account = models.OneToOneField(Account, unique=True)
code = models.CharField(max_length=128)
timestamp = models.DateTimeField(auto_now_add=True)
Controller
def confirm(confirmData: dict) -> bool:
"""
Activates the account associated with the given code.
:param confirmData: The data needed to confirm the account.
:return: Whether the activation was successful.
"""
form = forms.ConfirmForm(confirmData)
if not form.is_valid():
return False
data = form.cleaned_data
try:
confirmObject = ActivationCode.objects.get(code=data['code'])
except ActivationCode.DoesNotExist:
return False
confirmObject.account.activated = True
confirmObject.account.save()
confirmObject.delete()
return True
The test that failes
class ActivateTest(TestCase):
def setUp(self):
controller.register(testUser)
def testActivateSingleUser(self):
account = User.objects.get(username=testUser['username']).account
success = controller.confirm({'code': account.activationcode.code})
account.refresh_from_db()
self.assertTrue(success)
self.assertTrue(account.activated)
# account.activationcode.refresh_from_db() # uncommenting this line will result in a DoesNotExist exception
self.assertFalse(hasattr(account, 'activationcode')) # This test fails.
Finally the Traceback
FAIL: testActivateSingleUser (Main.tests.ActivateTest) ---------------------------------------------------------------------- Traceback (most recent call last): File "C:\Users\Path\To\Project\Main\tests.py", line 53, in testActivateSingleUser self.assertFalse(hasattr(account, 'activationcode')) AssertionError: True is not false
Duplicate of #27846, should be fixed in Django 2.0.