﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
34137	model.refresh_from_db() doesn't  clear cached generic foreign keys	pascal chambon	Bhuvnesh	"In my code, Users have a generic foreign key like so: 

{{{
    controlled_entity_content_type = models.ForeignKey(ContentType, blank=True, null=True, on_delete=models.CASCADE)
    controlled_entity_object_id = models.PositiveIntegerField(blank=True, null=True)
    controlled_entity = GenericForeignKey(""controlled_entity_content_type"", ""controlled_entity_object_id"")
}}}

However, in unit-tests, when I refresh a user instance, the controlled_entity relation isn't cleared from cache, as can be seen here with IDs: 


{{{
        old_controlled_entity = authenticated_user.controlled_entity
        authenticated_user.refresh_from_db()
        new_controlled_entity = authenticated_user.controlled_entity
        assert id(old_controlled_entity) != id(new_controlled_entity)   # FAILS
}}}


And this leads to subtle bugs like non-transitive equalities in tests :


{{{
        assert authenticated_user.controlled_entity == fixtures.client1_project2_organization3
        assert fixtures.client1_project2_organization3.get_pricing_plan() == pricing_plan
        assert authenticated_user.controlled_entity.get_pricing_plan() == pricing_plan     # FAILS
}}}

Calling ""authenticated_user.controlled_entity.refresh_from_db()"" solved this particular bug, but ""authenticated_user.refresh_from_db()"" isn't enough.


Tested under Django3.2.13 but the code of refresh_from_db() hasn't changed since then in Git's main branch (except few cosmetic adjustments on code format).

I'm a bit lost in the code of refresh_from_db(), but I've just seen that the generic relation appears once in this loop, but is not considered as ""cached"" in the if() branch.

{{{
        for field in self._meta.related_objects:
            #print(""%% CLEARING RELATED FIELD"", field)
            if field.is_cached(self):
                #print(""%% DONE"")   # not called
                field.delete_cached_value(self)
}}}


"	Bug	closed	contrib.contenttypes	3.2	Normal	fixed		Simon Charette	Ready for checkin	1	0	0	0	0	0
