djangodjango-modelsdjango-signals

Django Signals : Access ManyToManyRel value from instance


I have the following signal :

@receiver(post_save, sender=Document)
def handle_added_or_edited_element(sender, instance, **kwargs):
    '''
    This signal is used to compare the original and the current instance of the object being saved.
    If at least one field has changed, a row is inserted in the revision history of the related srd_revision
    '''
    for field in sender._meta.get_fields():
        if field.name in ['srd_revision', 'srdrevision', 'srd_rev']:
            print(instance._meta.get_fields()[0])
        if not isinstance(field, (models.ManyToOneRel, models.ManyToManyRel)):
            if instance._get_field_value_map(instance._meta)[field.name].value != instance.__original_instance._get_field_value_map(instance._meta)[field.name].value:
                chapter, message = RevisionHistory().get_document_messages(instance=instance, created=False, updated_field=field.name)
                SrdRevisionHistory(chapter=chapter, title=message)

This two lines :

if field.name in ['srd_revision', 'srdrevision', 'srd_rev']:
    print(instance._meta.get_fields()[0])

Gives me a ManyToManyRel : <ManyToManyRel: srdapp.srdrevision>

I would like to access the id of the srdrevision object related to the Document object.


Solution

  • instance._meta.get_fields()[0] is a queryset object (since it is coming from a M2M relation). Not sure if this is what you're looking for but you can print srdrevision's ids like print(instance.srdrevision.values_list("id", flat=True)) which prints all of your relation ids (all the ids related to this object and of srdrevision type).

    Note that you can not grab one specific id because there might more that one object of type srdrevision related to your instance here!

    You need to also check instance._meta.get_fields()[0] type before doing something else because it might not be always M2M type.