def _track_class_related_field(cls, field):
    """ Track a field on a related model """
    # field = field on current model
    # related_field = field on related model
    (field, related_field) = field.split('__', 1)
    field_obj = cls._meta.get_field(field)
    related_cls = field_obj.remote_field.model
    related_name = field_obj.remote_field.get_accessor_name()

    if not hasattr(related_cls, '_tracked_related_fields'):
        setattr(related_cls, '_tracked_related_fields', {})
    if related_field not in related_cls._tracked_related_fields.keys():
        related_cls._tracked_related_fields[related_field] = []

    # There can be several field from different or same model
    # related to a single model.
    # Thus _tracked_related_fields will be of the form:
    # {
    #     'field name on related model': [
    #         ('field name on current model', 'field name to current model'),
    #         ('field name on another model', 'field name to another model'),
    #         ...
    #     ],
    #     ...
    # }

    related_cls._tracked_related_fields[related_field].append(
        (field, related_name)
    )
    _add_signals_to_cls(related_cls)
    # Detect m2m fields changes
    if isinstance(related_cls._meta.get_field(related_field), ManyToManyField):
        m2m_changed.connect(
            tracking_m2m,
            sender=getattr(related_cls, related_field).through,
            dispatch_uid=repr(related_cls),
        )
Track a field on a related model