django-stubs
django-stubs copied to clipboard
Need type annotation for ManyToManyField with string class names
Bug report
What's wrong
I'm looking at updating from 4.2.4 to 4.2.6, and am seeing some new errors that I'm not sure how to handle. They're all in one single models.py file, are all ManyToManyFields, and each of those contain the related class name as a string not as the class itself. For the ones I can convert from strings to classes without having to re-order models, this fixes the error. I don't see this particular issue discussed in a any release notes / issues / MRs hence I'm asking here. Is this expected with this update, and what should I be doing about this error? The fact that I only see this in one file is suspicious to me, but we have very few other ManyToManyFields so I can't narrow it down to something breaking in this file just yet.
models.py
destinations = models.ManyToManyField('Destination')
now leads to:
error: Need type annotation for "destinations" [var-annotated]
and when I change the model to
destinations = models.ManyToManyField(Destination)
the error is gone.
How is that should be
Not sure tbh. If strings are not supported then I'd expect that to be mentioned somewhere (if it is, apologies!)
System information
- OS: MacOS 13.6
-
python
version: 3.11 -
django
version: 4.2.6 -
mypy
version: 1.6.1 -
django-stubs
version: 4.2.6 -
django-stubs-ext
version: 4.2.5
Lazy references are supported if you use the format "<app_label>.<model_name>"
. Lazy reference with implicit app label isn't supported
Ah OK yes that's the difference between this module and the ManyToManyFields in our other apps. Just to clarify and for the next person that finds this, implicit app name is supported by ForeignKey and OneToOneField, but not ManyToManyField? As I don't see issues with those relationships.
Same here. I only have this error since I updated mypy from 1.5.1
to 1.6.1
and django-stubs from 4.2.4
to 4.2.6
and ONLY on ManyToManyField
(not ForeignKey
). Seems weird.
[Edit] Seems closely related to this #1719 change
I have a ManyToManyField
where the through
model is referenced with a string class name. I needed to provide a type annotation as follows:
related_field: models.ManyToManyField[ToModel, 'ThroughModel'] = models.ManyToManyField(to=ToModel, through='ThroughModel')
Sorry, this is slightly unrelated: What's the correct type annotation for the through model when it is not a custom one?
What's the correct type annotation for the through model when it is not a custom one?
Short answer: There is no correct type annotation.
Long answer:
The plugin mimics Django's dynamic creation of the intermediate(through) model, ref: https://github.com/django/django/blob/40b3975e7d3e1464a733c69171ad7d38f8814280/django/db/models/fields/related.py#L1281-L1319
So you'll need a declaration identical to that, but once you type it out you might as well use what you type out explicitly as a through=
argument.
any resolution on this issue?
Hello @masarliev , try with <app_label>.<model_name>
e.g.
models.ManyToManyField(
to='<app_label>.<model_name>',
...
Hello @masarliev , try with
<app_label>.<model_name>
e.g.models.ManyToManyField( to='<app_label>.<model_name>', ...
not working. for now I changed all relations to field: models.ManyToManyField = models.ManyToManyField..... and works, but I don't like anotating all relations just for mypy
not working.
Did you do the same for through
parameters as well? This fixed the issue for me without annotations, but I had to do both to
and through
.