def on_m2m_changed(self, sender, **kwargs):
        if self._in_migration:
            return
        if kwargs['reverse'] is False:
            objs = [kwargs['instance']]
            model = objs[0].__class__
        else:
            model = kwargs['model']
            objs = model.objects.filter(pk__in=kwargs['pk_set'])
        mod_name = model_name(model)
        if mod_name.split('.', 1)[0] in ('migrations', 'dddp'):
            return  # never send migration or DDP internal models
        # See https://docs.djangoproject.com/en/1.7/ref/signals/#m2m-changed
        if kwargs['action'] in (
                'pre_add',
                'pre_remove',
                'pre_clear',
        ):
            for obj in objs:
                self.on_pre_change(
                    sender=model, instance=obj, using=kwargs['using'],
                )
        elif kwargs['action'] in (
                'post_add',
                'post_remove',
                'post_clear',
        ):

            for obj in objs:
                self.send_notify(
                    model=model,
                    obj=obj,
                    msg=CHANGED,
                    using=kwargs['using'],
                )
Return the product of array elements over a given axis treating Not a
dataset/ETHPy150Open django-ddp/django-ddp/dddp/api.py/DDP.on_m2m_changed--crossover with--dataset/ETHPy150Open pydata/xarray/xarray/core/npcompat.py/nanprod