diff --git a/mypy_django_plugin/transformers/models.py b/mypy_django_plugin/transformers/models.py index 52ef3ca1d..7b5d7059c 100644 --- a/mypy_django_plugin/transformers/models.py +++ b/mypy_django_plugin/transformers/models.py @@ -363,7 +363,7 @@ def run_with_model_cls(self, model_cls: Type[Model]) -> None: self.add_new_node_to_model_class( attname, Instance(default_reverse_manager_info, []), no_serialize=True ) - return + continue # The reverse manager we're looking for doesn't exist. So we create it. # The (default) reverse manager type is built from a RelatedManager and the default manager on the related model diff --git a/tests/typecheck/models/test_related_fields.yml b/tests/typecheck/models/test_related_fields.yml new file mode 100644 index 000000000..b9a801980 --- /dev/null +++ b/tests/typecheck/models/test_related_fields.yml @@ -0,0 +1,89 @@ +- case: test_related_name_custom_manager + main: | + from app1.models import Model1 + from app2.models import Model2 + + reveal_type(Model1().test) # N: Revealed type is "app3.models.Model3_RelatedManager" + reveal_type(Model2().test) # N: Revealed type is "app3.models.Model3_RelatedManager" + reveal_type(Model1().test2) # N: Revealed type is "app3.models.Model4_RelatedManager" + reveal_type(Model2().test2) # N: Revealed type is "app3.models.Model4_RelatedManager" + installed_apps: + - base + - users + - app1 + - app2 + - app3 + files: + - path: base/__init__.py + - path: base/models.py + content: | + from django.db import models + class OwnedModel(models.Model): + owner = models.ForeignKey("users.User", on_delete=models.CASCADE) + + class Meta: + abstract = True + + - path: users/__init__.py + - path: users/models.py + content: | + from django.db import models + class User(models.Model): + pass + + - path: app1/__init__.py + - path: app1/models.py + content: | + from django.db import models + from base.models import OwnedModel + from typing import TYPE_CHECKING + if TYPE_CHECKING: + from app3.models import Model3 + + class CustomQuerySet(models.QuerySet): + pass + + Model1Manager = models.Manager.from_queryset(CustomQuerySet) + class Model1(OwnedModel): + objects = Model1Manager() + + - path: app2/__init__.py + - path: app2/models.py + content: | + from django.db import models + from base.models import OwnedModel + from typing import TYPE_CHECKING + if TYPE_CHECKING: + from app3.models import Model3 + + class CustomQuerySet(models.QuerySet): + pass + + Model2Manager = models.Manager.from_queryset(CustomQuerySet) + class Model2(OwnedModel): + objects = Model2Manager() + + - path: app3/__init__.py + - path: app3/models.py + content: | + from django.db import models + from app1.models import Model1 + from app2.models import Model2 + from base.models import OwnedModel + + class CustomQuerySet(models.QuerySet): + pass + + Model3Manager = models.Manager.from_queryset(CustomQuerySet) + class Model3(OwnedModel): + a = models.ForeignKey(Model1, related_name="test", on_delete=models.CASCADE) + b = models.ForeignKey(Model2, related_name="test", on_delete=models.CASCADE) + + objects = Model3Manager() + + Model4Manager = models.Manager.from_queryset(CustomQuerySet) + class Model4(OwnedModel): + a = models.ForeignKey(Model1, related_name="test2", on_delete=models.CASCADE) + b = models.ForeignKey(Model2, related_name="test2", on_delete=models.CASCADE) + + objects = Model4Manager()