Split AddManagers for model in separate stages to process IncompleteDefnException properly (#171)

This commit is contained in:
Maxim Kurnikov
2019-09-18 02:20:20 +03:00
committed by GitHub
parent 23ad65033b
commit 29ac1c3017
2 changed files with 34 additions and 4 deletions

View File

@@ -121,7 +121,7 @@ class AddManagers(ModelClassInitializer):
manager_type = Instance(manager_info, [Instance(self.model_classdef.info, [])]) manager_type = Instance(manager_info, [Instance(self.model_classdef.info, [])])
self.add_new_node_to_model_class(manager_name, manager_type) self.add_new_node_to_model_class(manager_name, manager_type)
else: else:
# create new MODELNAME_MANAGERCLASSNAME class that represents manager parametrized with current model # creates new MODELNAME_MANAGERCLASSNAME class that represents manager parametrized with current model
has_manager_any_base = any(self._is_manager_any(base) for base in manager_info.bases) has_manager_any_base = any(self._is_manager_any(base) for base in manager_info.bases)
if has_manager_any_base: if has_manager_any_base:
custom_model_manager_name = manager.model.__name__ + '_' + manager.__class__.__name__ custom_model_manager_name = manager.model.__name__ + '_' + manager.__class__.__name__
@@ -129,8 +129,8 @@ class AddManagers(ModelClassInitializer):
for original_base in manager_info.bases: for original_base in manager_info.bases:
if self._is_manager_any(original_base): if self._is_manager_any(original_base):
if original_base.type is None: if original_base.type is None:
if not self.api.final_iteration: raise helpers.IncompleteDefnException()
self.api.defer()
original_base = helpers.reparametrize_instance(original_base, original_base = helpers.reparametrize_instance(original_base,
[Instance(self.model_classdef.info, [])]) [Instance(self.model_classdef.info, [])])
bases.append(original_base) bases.append(original_base)
@@ -142,6 +142,9 @@ class AddManagers(ModelClassInitializer):
custom_manager_type = Instance(custom_manager_info, [Instance(self.model_classdef.info, [])]) custom_manager_type = Instance(custom_manager_info, [Instance(self.model_classdef.info, [])])
self.add_new_node_to_model_class(manager_name, custom_manager_type) self.add_new_node_to_model_class(manager_name, custom_manager_type)
class AddDefaultManagerAttribute(ModelClassInitializer):
def run_with_model_cls(self, model_cls: Type[Model]) -> None:
# add _default_manager # add _default_manager
if '_default_manager' not in self.model_classdef.info.names: if '_default_manager' not in self.model_classdef.info.names:
default_manager_fullname = helpers.get_class_fullname(model_cls._meta.default_manager.__class__) default_manager_fullname = helpers.get_class_fullname(model_cls._meta.default_manager.__class__)
@@ -149,6 +152,9 @@ class AddManagers(ModelClassInitializer):
default_manager = Instance(default_manager_info, [Instance(self.model_classdef.info, [])]) default_manager = Instance(default_manager_info, [Instance(self.model_classdef.info, [])])
self.add_new_node_to_model_class('_default_manager', default_manager) self.add_new_node_to_model_class('_default_manager', default_manager)
class AddRelatedManagers(ModelClassInitializer):
def run_with_model_cls(self, model_cls: Type[Model]) -> None:
# add related managers # add related managers
for relation in self.django_context.get_model_relations(model_cls): for relation in self.django_context.get_model_relations(model_cls):
attname = relation.get_accessor_name() attname = relation.get_accessor_name()
@@ -231,6 +237,8 @@ def process_model_class(ctx: ClassDefContext,
AddDefaultPrimaryKey, AddDefaultPrimaryKey,
AddRelatedModelsId, AddRelatedModelsId,
AddManagers, AddManagers,
AddDefaultManagerAttribute,
AddRelatedManagers,
AddExtraFieldMethods, AddExtraFieldMethods,
AddMetaOptionsAttribute, AddMetaOptionsAttribute,
RecordAllModelMixins, RecordAllModelMixins,

View File

@@ -571,4 +571,26 @@
class Book(LibraryEntity): class Book(LibraryEntity):
pass pass
class Article(LibraryEntity): class Article(LibraryEntity):
pass pass
- case: foreign_key_relationship_for_models_with_custom_manager
main: |
from myapp.models import Transaction
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
content: |
from django.db import models
class TransactionQuerySet(models.QuerySet):
pass
class Transaction(models.Model):
objects = TransactionQuerySet.as_manager()
def test(self) -> None:
self.transactionlog_set
class TransactionLog(models.Model):
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE)
Transaction().test()