def _collect_sub_objects(self, seen_objs):
        """
        Recursively populates seen_objs with all objects related to this object.
        When done, seen_objs will be in the format:
            {model_class: {pk_val: obj, pk_val: obj, ...},
             model_class: {pk_val: obj, pk_val: obj, ...}, ...}
        """
        pk_val = self._get_pk_val()
        if pk_val in seen_objs.setdefault(self.__class__, {}):
            return
        seen_objs.setdefault(self.__class__, {})[pk_val] = self

        for related in self._meta.get_all_related_objects():
            rel_opts_name = related.get_accessor_name()
            if isinstance(related.field.rel, OneToOneRel):
                try:
                    sub_obj = getattr(self, rel_opts_name)
                except __HOLE__:
                    pass
                else:
                    sub_obj._collect_sub_objects(seen_objs)
            else:
                for sub_obj in getattr(self, rel_opts_name).all():
                    sub_obj._collect_sub_objects(seen_objs)
dataset/ETHPy150Open AppScale/appscale/AppServer/lib/django-0.96/django/db/models/base.py/Model._collect_sub_objects