'This method is used by each model to find its reverse objects. As this
method is very expensive and is accessed frequently (it looks up every
field in a model, in every app), it is computed on first access and then
is set as a property on every model.'

def _populate_directed_relation_graph(self):

    related_objects_graph = defaultdict(list)
    all_models = self.apps.get_models(include_auto_created=True)
    for model in all_models:
        opts = model._meta
        if opts.abstract:
            continue
        fields_with_relations = (f for f in opts._get_fields(reverse=False, include_parents=False) if (f.is_relation and (f.related_model is not None)))
        for f in fields_with_relations:
            if (not isinstance(f.remote_field.model, str)):
                related_objects_graph[f.remote_field.model._meta.concrete_model._meta].append(f)
    for model in all_models:
        related_objects = related_objects_graph[model._meta.concrete_model._meta]
        model._meta.__dict__['_relation_tree'] = related_objects
    return self.__dict__.get('_relation_tree', EMPTY_RELATION_TREE)
