[Django]-Get selected values of ManytoMany field in django model save method

0👍

The problem is that your BillRecord instance is not always saved when a Product is associated with it. With a many to many relation, you can save either object first. The correct way to deal with it is to use the m2m-changed signal:

Sent when a ManyToManyField is changed on a model instance. Strictly speaking, this is not a model signal since it is sent by the ManyToManyField, but since it complements the pre_save/post_save and pre_delete/post_delete when it comes to tracking changes to models, it is included here.

So you should try something like the following:

from django.db.models.signals import m2m_changed

...your models here...

def products_changed(sender, **kwargs):
    # Do something here
    pass

m2m_changed.connect(products_changed, sender=BillRecord.products.through)
👤Selcuk

0👍

There are three kind of action in m2m: add, remove, clean

the signal @receiver(m2m_changed, sender=Model.manytomanyfield.through) iterate actions:

first:

pre-remove and post-remove: if some objects are removed from your manytomanyfield
then to pre-add, here you can access to your selected (new) values and to the instance (with the removed objects of manytomanyfield).
You could write something like that to get them:

@receiver(m2m_changed, sender=ProductVariation.combination.through)

def check_attribute(sender, **kwargs):
instance = kwargs[‘instance’]

import pdb; pdb.set_trace()
if kwargs['action'] == 'pre_add':
    if kwargs.get('pk_set'):
        product_attributes = instance.combination.all() | \
                             ProductAttribute.objects.filter(id__in=kwargs.get('pk_set'))
        groups_count = product_attributes.values('attribute').annotate(Count('id'))
        for group in groups_count:
            if group.get('id__count', 0) > 1:
                attribute_name = Attribute.objects.get(id=group['attribute'])
                rai

Leave a comment