1
1
from __future__ import annotations
2
2
3
+ import inspect
3
4
from collections import defaultdict
5
+ from types import ModuleType
4
6
5
7
from django .apps .registry import Apps
6
8
from django .conf import LazySettings
@@ -25,12 +27,26 @@ def __init__(self, apps: Apps, settings: LazySettings) -> None:
25
27
26
28
@staticmethod
27
29
def _get_model_alias (model : ModelType ) -> str :
28
- """Return an alias of the model, by converting the app label to PascalCase and joining
30
+ """Return an alias of the model.
31
+
32
+ The alias is constructed by converting the app label to PascalCase and joining
29
33
the app label to the model name.
30
34
"""
31
35
app_label = to_pascal (model ._meta .app_label )
32
36
return f"{ app_label } { model .__name__ } "
33
37
38
+ @staticmethod
39
+ def _get_model_module (model : ModelType ) -> ModuleType :
40
+ """Return the module object where the model class is exported or defined.
41
+
42
+ Use the models module of the app where the model is defined, and fallback
43
+ to the actual module of the model class in case the model is not exported
44
+ or present in the models module.
45
+ """
46
+ if model ._meta .app_config .models_module is not None :
47
+ return model ._meta .app_config .models_module
48
+ return inspect .getmodule (model ) # type: ignore
49
+
34
50
@property
35
51
def models (self ) -> list [ModelType ]:
36
52
"""All the defined models. Abstract models are not included."""
@@ -45,7 +61,7 @@ def model_imports(self) -> list[ImportItem]:
45
61
46
62
return [
47
63
ImportItem (
48
- module_name = model . _meta . app_config . models_module .__name__ ,
64
+ module_name = self . _get_model_module ( model ) .__name__ ,
49
65
obj_name = model .__name__ ,
50
66
alias = self ._get_model_alias (model ) if self .is_duplicate (model ) else None ,
51
67
)
0 commit comments