def tracking_m2m(
        sender, instance, action, reverse, model, pk_set, using, **kwargs
):
    """
    m2m_changed callback.
    The idea is to get the model and the instance of the object being tracked,
    and the different objects being added/removed. It is then send to the
    ``_create_tracked_field_m2m`` method to extract the proper attribute for
    the TrackedFieldModification.
    """
    action_event = {
        'pre_clear': 'CLEAR',
        'pre_add': 'ADD',
        'pre_remove': 'REMOVE',
    }
    if (action not in action_event.keys()):
        return
    if reverse:
        if action == 'pre_clear':
            # It will actually be a remove of ``instance`` on every
            # tracked object being related
            action = 'pre_remove'
            # pk_set is None for clear events, we need to get objects' pk.
            field = _get_m2m_field(model, sender)
            field = model._meta.get_field(field).remote_field.get_accessor_name()
            pk_set = set([obj.id for obj in getattr(instance, field).all()])
        # Create an event for each object being tracked
        for pk in pk_set:
            tracked_instance = model.objects.get(pk=pk)
            objects = [instance]
            _create_tracked_event_m2m(
                model, tracked_instance, sender, objects, action_event[action]
            )
    else:
        # Get the model of the object being tracked
        tracked_model = instance._meta.model
        objects = []
        if pk_set is not None:
            objects = [model.objects.get(pk=pk) for pk in pk_set]
        _create_tracked_event_m2m(
            tracked_model, instance, sender, objects, action_event[action]
        )
def tracking_m2m ( sender , instance , action , reverse , model , pk_set , using , ** kwargs ) : action_event = { 'pre_clear' : 'CLEAR' , 'pre_add' : 'ADD' , 'pre_remove' : 'REMOVE' , } if ( action not in action_event . keys ( ) ) : return if reverse : if action == 'pre_clear' : action = 'pre_remove' field = _get_m2m_field ( model , sender ) field = model . _meta . get_field ( field ) . remote_field . get_accessor_name ( ) pk_set = set ( [ obj . id for obj in getattr ( instance , field ) . all ( ) ] ) for pk in pk_set : tracked_instance = model . objects . get ( pk = pk ) objects = [ instance ] _create_tracked_event_m2m ( model , tracked_instance , sender , objects , action_event [ action ] ) else : tracked_model = instance . _meta . model objects = [ ] if pk_set is not None : objects = [ model . objects . get ( pk = pk ) for pk in pk_set ] _create_tracked_event_m2m ( tracked_model , instance , sender , objects , action_event [ action ] )
m2m_changed callback.
    The idea is to get the model and the instance of the object being tracked,
    and the different objects being added/removed. It is then send to the
    ``_create_tracked_field_m2m`` method to extract the proper attribute for
    the TrackedFieldModification.