Closed yoav-orca closed 2 years ago
I think the ManyToMany needs to be typed as:
publications = models.ManyToManyField[Publication, Any](Publication)
# or maybe
publications = models.ManyToManyField[Publication, object](Publication)
I think the second type argument is the through
param which is optional.
I don't think there is a way to provide a default generic param though, maybe we could handle it with overloads?
Edit: it might be worth reviewing whether the extra generic param for the through
table hurts more than it helps aka maybe we should remove it
Edit: it might be worth reviewing whether the extra generic param for the through table hurts more than it helps aka maybe we should remove it
This hurts a lot for people that uses through
though, because it makes it impossible to have the intermediate table automatically typed when you do this. For example, most of my ManyToMany fields that I use in my projects usually has a through
table, which contains intermediate information.
I don't know much about how mypy --strict
works, but shouldn't it fall to this overload: https://github.com/sbdchd/django-types/blob/main/django-stubs/db/models/fields/related.pyi#L427 ?
Also, it seems that the problem is related to the fact that there's a __init__
together with __new__
. The real proper way to fix this and any other issues, which should also work for both mypy and pyright, would be to remove all __init__
from all fields and keep just the __new__
in them. That would mean having to quadruplicate the __new__
signature in all of them. Maybe it is for the best to do that?
IMO this can probably be closed as it was already solved.
So how can we actually annotate a ManyToManyField
? Is it worth adding this to the docs?
So how can we actually annotate a
ManyToManyField
? Is it worth adding this to the docs?
The same way as @sbdchd suggested, but you can pass the through
model as the second argument if you have any.
e.g.:
publications = models.ManyToManyField[Publication, Any](Publication)
publications = models.ManyToManyField[Publication, object](Publication)
# to be at least more specific that it is a Model subclass
publications = models.ManyToManyField[Publication, models.Model](Publication)
# for ManyToManyField with through
publications = models.ManyToManyField[Publication, "ArticlePublication"](
Publication,
through="ArticlePublication",
)
And IMO probably worth mentioning in the docs
In what Python version are you able to subscript ManyToManyField
like that?
TypeError: type 'ManyToManyField' is not subscriptable
Python 3.11, Django 4.2.4
In what Python version are you able to subscript
ManyToManyField
like that?TypeError: type 'ManyToManyField' is not subscriptable
Python 3.11, Django 4.2.4
You need to install and use the django_stubs_ext package, or monkey patch it yourself like this:
for cls in [
QuerySet,
RawQuerySet,
BaseManager,
models.ForeignKey,
models.JSONField,
models.ManyToManyField,
]:
cls.__class_getitem__ = classmethod(lambda cls, *args, **kwargs: cls)
I personally monkey patch it myself as it seems easier for me =P
Ah! I can't believe I missed that! Probably because I haven't had to install it so far, I haven't needed it for Manager[Model]
etc. Perhaps these have been added to Django now. This is the first time I've needed it.
I want to migrate away from the django mypy plugin (it currently doesn't work for newer mypy versions).
I have taken this example from the Django website:
Running mypy version (0.910) on this file: