Opened 7 years ago

Closed 7 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  

Change History (1)

comment:1 by Claude Paroz, 7 years ago

Resolution: duplicate
Status: newclosed

Duplicate of #27846, should be fixed in Django 2.0.

Note: See TracTickets for help on using tickets.
Back to Top