Opened 3 years ago

Closed 3 years ago

#33276 closed Cleanup/optimization (wontfix)

Strange difference for prefetched_objects between related_field.remove, m2m_related_field.remove and generic_related_field.remove.

Reported by: Maxim Danilov Owned by: nobody
Component: Database layer (models, ORM) Version: 3.2
Severity: Normal Keywords: prefetch_related
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description

Hello.

i want to call _remove_prefetched_objects only to remove cached old data. But i dont want to use private method.

instance.m2m_related_field.remove() - made what i want.

instance.generic_related_field.remove() - Does nothing
instance.related_field.remove() - Does nothing

in django (> 3.2) code i see:

# (django.db.models.fields.related_descriptors 964-965)
# m2m_related_field
def remove(self, *objs):
    self._remove_prefetched_objects()
    ...


# (django.contrib.contenttypes.fields 635-645)
# generic_related_field
def remove(self, *objs, bulk=True):
    if not objs:
        return
    ...
    return self._clear(...)

def _clear(...):
    self._remove_prefetched_objects()


# (django.db.models.fields.related_descriptors 694-719)
# related_field
def remove(self, *objs, bulk=True):
    if not objs:
        return
    ....
    return self_clear(...)

def _clear(...):
    self._remove_prefetched_objects()

i think, It is better to made the same functionality in remove method for all related fields.

# for all related fields:
def remove(self, *objs):
    self._remove_prefetched_objects()
    if objs:
        return self._do_something_to_remove(....)

This made a removal interface more standard.

Change History (1)

comment:1 by Carlton Gibson, 3 years ago

Resolution: wontfix
Status: newclosed

Hi Maxim.

i want to call _remove_prefetched_objects only to remove cached old data. But i dont want to use private method.

instance.m2m_related_field.remove() - made what i want.

This doesn't sound right. 🤔
remove() will (erm) remove the objects from the M2M relation, not just remove cached old data — it alters the data in the DB.

If you just want to remove the prefetch cache I think you'll need to use the private method, or call refresh_from_db(), or similar.

The _clear() method is a shared helper between remove() and clear(). Moving the _remove_prefetched_objects() to the public methods will just cause duplication of the implementation there. I don't think that's a change we want to make.

Thanks.

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