Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

error: Couldn't resolve related manager for relation on python3.11 and django3.2 #1354

Closed
marsha97 opened this issue Jan 31, 2023 · 8 comments
Labels
bug Something isn't working mypy-plugin Issues specific to mypy_django_plugin

Comments

@marsha97
Copy link

Bug report

What's wrong

I got Couldn't resolve related manager for relation error when using python3.11 and django3.2.
So the model looks like

# dummy/apps/foos/models.py

class Foo(models.Model):
    ....
# dummy/apps/bars/models.py

class BarQueryset(models.Queryset):
    ...

class Bar(models.Model):
    ...
   foo = models.Foreignkey('foos.Foo', related_name='bars')
   objects = models.Manager.from_queryset(BarQueryset)()

I will get the following error:
dummy/apps/foos/models.py:###: error: Couldn't resolve related manager for relation 'bars' (from dummy.apps.bars.models.Bar.bars.Bar.foo). [django-manager-missing]

It seems only happen when the reverse foreign key has a custom objects like Bar above...
And may be related to #1285

I have to use # type: ignore for now to silent this...

How is that should be

Should have no problem. I tried to downgrade python back to python3.9, mypy==0.812, and django-stubs==1.8.0 and it has no issue.

System information

  • OS: ubuntu 20
  • python version: 3.11
  • django version: 3.2.16
  • mypy version: 0.991
  • django-stubs version: 1.14.0
  • django-stubs-ext version: 0.7.0
@marsha97 marsha97 added the bug Something isn't working label Jan 31, 2023
@flaeppe flaeppe added the mypy-plugin Issues specific to mypy_django_plugin label Jan 31, 2023
@ljodal
Copy link
Contributor

ljodal commented Feb 6, 2023

I tried to downgrade python back to python3.9, mypy==0.812, and django-stubs==1.8.0 and it has no issue.

Are you sure you're getting typing on that setup? I introduced this error message a while back, but it was only to surface issues that were previously silently ignored.

Basically, this error means that the plugin was not able to statically figure out what class the manager would be. Typically that means you're doing something in your code that's not statically checkable (or not supported by the plugin). Are you able to create a minimal example that reproduces the issue?

@marsha97
Copy link
Author

marsha97 commented Feb 6, 2023

I tried to downgrade python back to python3.9, mypy==0.812, and django-stubs==1.8.0 and it has no issue.

Are you sure you're getting typing on that setup? I introduced this error message a while back, but it was only to surface issues that were previously silently ignored.

Basically, this error means that the plugin was not able to statically figure out what class the manager would be. Typically that means you're doing something in your code that's not statically checkable (or not supported by the plugin). Are you able to create a minimal example that reproduces the issue?

ooh, right. I noticed something else, this will happen if the reverse FK class inherit from this 3rd party class https://github.com/jazzband/django-model-utils/blob/cced1c7aeaf97fa6ee5c7e44c8ea827ed10b2da5/model_utils/models.py#L19
Still has no idea how to resolve this

so the simple code will looks like:

# apps/foos/models.py

from django.db import models


class Foo(models.Model):
    field1 = models.PositiveSmallIntegerField()
# apps/bars/models.py

from django.db import models
from model_utils.models import TimeStampedModel


class BarQueryset(models.QuerySet):
    def get_active_qs(self) -> models.QuerySet:
        return self.filter(is_active=True)


class Bar(TimeStampedModel):
    foo = models.ForeignKey("foos.Foo", related_name="bars", on_delete=models.CASCADE)
    is_active = models.BooleanField(default=False)
    objects = models.Manager.from_queryset(BarQueryset)()

this will results in:
dummy/apps/foos/models.py:4: error: Couldn't resolve related manager for relation 'bars' (from dummy.apps.bars.models.Bar.bars.Bar.foo). [django-manager-missing]

removing the custom objects attribute will produce the same error.

but, it will be fine if I changed the Bar model into something like this:

from django.db import models


class BarQueryset(models.QuerySet):
    def get_active_qs(self) -> models.QuerySet:
        return self.filter(is_active=True)


class BaseBar(models.Model):
    name = models.CharField(max_length=255)


class Bar(BaseBar):
    foo = models.ForeignKey("foos.Foo", related_name="bars", on_delete=models.CASCADE)
    is_active = models.BooleanField(default=False)
    objects = models.Manager.from_queryset(BarQueryset)()

@ljodal
Copy link
Contributor

ljodal commented Feb 6, 2023

Ah, alright. I guess the error message could be improved here, but basically it appears that TimeStampedModel has its managers dynamically added, which is hard/impossible to statically type check.

@intgr
Copy link
Collaborator

intgr commented Feb 6, 2023

I didn't look into this in detail, but maybe it helps to add manual type hints to the Model class for these manager attributes?

@baileywickham
Copy link

I was able to fix this issue by annotating the related name. In this case it would be

class Foo:
    field1 = models.PositiveSmallIntegerField()
    bars: "QuerySet[Bar]"
    # or if related_name isn't set:
    bar_set: "QuerySet[Bar]"

@ibadarrohman
Copy link

ibadarrohman commented Jul 26, 2023

I was able to fix this issue by annotating the related name. In this case it would be

class Foo:
    field1 = models.PositiveSmallIntegerField()
    bars: "QuerySet[Bar]"
    # or if related_name isn't set:
    bar_set: "QuerySet[Bar]"

Annotating with RelatedManager[Bar] from django.db.models.manager.RelatedManager also works.

@flaeppe
Copy link
Member

flaeppe commented Sep 24, 2023

I deem that either any of the suggested approaches with explicit annotation is a resolution or if there's 3rd party code involved(ref: #1354 (comment)) this is a duplicate of #1023.

Feel free to correct me if I'm wrong.

@flaeppe flaeppe closed this as not planned Won't fix, can't repro, duplicate, stale Sep 24, 2023
@browser-bug
Copy link

I was able to fix this issue by annotating the related name. In this case it would be

class Foo:
    field1 = models.PositiveSmallIntegerField()
    bars: "QuerySet[Bar]"
    # or if related_name isn't set:
    bar_set: "QuerySet[Bar]"

Annotating with RelatedManager[Bar] from django.db.models.manager.RelatedManager also works.

This would throw Module "django.db.models.manager" has no attribute "RelatedManager" , correct me if I'm wrong.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working mypy-plugin Issues specific to mypy_django_plugin
Development

No branches or pull requests

7 participants