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.
(self)
| 806 | return path |
| 807 | |
| 808 | def _populate_directed_relation_graph(self): |
| 809 | """ |
| 810 | This method is used by each model to find its reverse objects. As this |
| 811 | method is very expensive and is accessed frequently (it looks up every |
| 812 | field in a model, in every app), it is computed on first access and |
| 813 | then is set as a property on every model. |
| 814 | """ |
| 815 | related_objects_graph = defaultdict(list) |
| 816 | |
| 817 | all_models = self.apps.get_models(include_auto_created=True) |
| 818 | for model in all_models: |
| 819 | opts = model._meta |
| 820 | # Abstract model's fields are copied to child models, hence we will |
| 821 | # see the fields from the child models. |
| 822 | if opts.abstract: |
| 823 | continue |
| 824 | fields_with_relations = ( |
| 825 | f |
| 826 | for f in opts._get_fields(reverse=False, include_parents=False) |
| 827 | if f.is_relation and f.related_model is not None |
| 828 | ) |
| 829 | for f in fields_with_relations: |
| 830 | if not isinstance(f.remote_field.model, str): |
| 831 | remote_label = f.remote_field.model._meta.concrete_model._meta.label |
| 832 | related_objects_graph[remote_label].append(f) |
| 833 | |
| 834 | for model in all_models: |
| 835 | # Set the relation_tree using the internal __dict__. In this way |
| 836 | # we avoid calling the cached property. In attribute lookup, |
| 837 | # __dict__ takes precedence over a data descriptor (such as |
| 838 | # @cached_property). This means that the _meta._relation_tree is |
| 839 | # only called if related_objects is not in __dict__. |
| 840 | related_objects = related_objects_graph[ |
| 841 | model._meta.concrete_model._meta.label |
| 842 | ] |
| 843 | model._meta.__dict__["_relation_tree"] = related_objects |
| 844 | # It seems it is possible that self is not in all_models, so guard |
| 845 | # against that with default for get(). |
| 846 | return self.__dict__.get("_relation_tree", EMPTY_RELATION_TREE) |
| 847 | |
| 848 | @cached_property |
| 849 | def _relation_tree(self): |
no test coverage detected