#34137: model.refresh_from_db() doesn't seem to clear cached generic foreign
keys
------------------------------------------+------------------------
Reporter: pascal chambon | Owner: nobody
Type: Uncategorized | Status: new
Component: Uncategorized | Version: 3.2
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
------------------------------------------+------------------------
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()" solevd
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)
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/34137>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/010701843d441525-be716ca7-973c-429c-bffb-cafd3a142e70-000000%40eu-central-1.amazonses.com.