code: 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':
              # 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]
          )
docs: 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.