1
- from typing import Dict , Optional , Type , cast
1
+ from typing import Dict , List , Optional , Type , cast
2
2
3
3
from django .db .models .base import Model
4
4
from django .db .models .fields import DateField , DateTimeField
@@ -58,6 +58,12 @@ def add_new_node_to_model_class(self, name: str, typ: MypyType) -> None:
58
58
name = name ,
59
59
sym_type = typ )
60
60
61
+ def add_new_class_for_current_module (self , name : str , bases : List [Instance ]) -> TypeInfo :
62
+ current_module = self .api .modules [self .model_classdef .info .module_name ]
63
+ new_class_info = helpers .add_new_class_for_module (current_module ,
64
+ name = name , bases = bases )
65
+ return new_class_info
66
+
61
67
def run (self ) -> None :
62
68
model_cls = self .django_context .get_model_class_by_fullname (self .model_classdef .fullname )
63
69
if model_cls is None :
@@ -164,14 +170,12 @@ def create_new_model_parametrized_manager(self, name: str, base_manager_info: Ty
164
170
[Instance (self .model_classdef .info , [])])
165
171
bases .append (original_base )
166
172
167
- current_module = self .api .modules [self .model_classdef .info .module_name ]
168
- custom_manager_info = helpers .add_new_class_for_module (current_module ,
169
- name = name , bases = bases )
173
+ new_manager_info = self .add_new_class_for_current_module (name , bases )
170
174
# copy fields to a new manager
171
- new_cls_def_context = ClassDefContext (cls = custom_manager_info .defn ,
175
+ new_cls_def_context = ClassDefContext (cls = new_manager_info .defn ,
172
176
reason = self .ctx .reason ,
173
177
api = self .api )
174
- custom_manager_type = Instance (custom_manager_info , [Instance (self .model_classdef .info , [])])
178
+ custom_manager_type = Instance (new_manager_info , [Instance (self .model_classdef .info , [])])
175
179
176
180
for name , sym in base_manager_info .names .items ():
177
181
# replace self type with new class, if copying method
@@ -185,10 +189,10 @@ def create_new_model_parametrized_manager(self, name: str, base_manager_info: Ty
185
189
new_sym = sym .copy ()
186
190
if isinstance (new_sym .node , Var ):
187
191
new_var = Var (name , type = sym .type )
188
- new_var .info = custom_manager_info
189
- new_var ._fullname = custom_manager_info .fullname + '.' + name
192
+ new_var .info = new_manager_info
193
+ new_var ._fullname = new_manager_info .fullname + '.' + name
190
194
new_sym .node = new_var
191
- custom_manager_info .names [name ] = new_sym
195
+ new_manager_info .names [name ] = new_sym
192
196
193
197
return custom_manager_type
194
198
@@ -268,15 +272,30 @@ def run_with_model_cls(self, model_cls: Type[Model]) -> None:
268
272
269
273
if isinstance (relation , (ManyToOneRel , ManyToManyRel )):
270
274
try :
271
- manager_info = self .lookup_typeinfo_or_incomplete_defn_error (fullnames .RELATED_MANAGER_CLASS )
275
+ related_manager_info = self .lookup_typeinfo_or_incomplete_defn_error (fullnames .RELATED_MANAGER_CLASS ) # noqa: E501
276
+ if 'objects' not in related_model_info .names :
277
+ raise helpers .IncompleteDefnException ()
272
278
except helpers .IncompleteDefnException as exc :
273
279
if not self .api .final_iteration :
274
280
raise exc
275
281
else :
276
282
continue
277
- self .add_new_node_to_model_class (attname ,
278
- Instance (manager_info , [Instance (related_model_info , [])]))
279
- continue
283
+
284
+ # create new RelatedManager subclass
285
+ parametrized_related_manager_type = Instance (related_manager_info ,
286
+ [Instance (related_model_info , [])])
287
+ default_manager_type = related_model_info .names ['objects' ].type
288
+ if (default_manager_type is None
289
+ or not isinstance (default_manager_type , Instance )
290
+ or default_manager_type .type .fullname == fullnames .MANAGER_CLASS_FULLNAME ):
291
+ self .add_new_node_to_model_class (attname , parametrized_related_manager_type )
292
+ continue
293
+
294
+ name = related_model_cls .__name__ + '_' + 'RelatedManager'
295
+ bases = [parametrized_related_manager_type , default_manager_type ]
296
+ new_related_manager_info = self .add_new_class_for_current_module (name , bases )
297
+
298
+ self .add_new_node_to_model_class (attname , Instance (new_related_manager_info , []))
280
299
281
300
282
301
class AddExtraFieldMethods (ModelClassInitializer ):
0 commit comments