#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.

Reply via email to