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

Incompatible types with ManyRelatedManager and through Model #2171

Closed
martinlehoux opened this issue May 20, 2024 · 2 comments
Closed

Incompatible types with ManyRelatedManager and through Model #2171

martinlehoux opened this issue May 20, 2024 · 2 comments
Labels
bug Something isn't working

Comments

@martinlehoux
Copy link
Contributor

Hi, when upgrading to version 5.0.0, I get a new error

class Establishment:
	equipments: models.ManyToManyField[Equipment, EquipmentEstablishmentMembership] = models.ManyToManyField(
	        Equipment,
	        through="EquipmentEstablishmentMembership",
	        blank=True,
	        related_name="establishments",
	    )

equipments_manager: manager.ManyRelatedManager[Equipment]
equipments_manager = instance.establishment.equipments # assignment error

The fulle error is Incompatible types in assignment (expression has type "Equipment_ManyRelatedManager[EquipmentEstablishmentMembership]", variable has type "ManyRelatedManager[Equipment, Model]")

When I looked at the source code, it seems that Equipment_ManyRelatedManager is generated by django stubs in certain cases. Is that expected that I receive this type in the calling code?

Thanks!

@martinlehoux martinlehoux added the bug Something isn't working label May 20, 2024
@flaeppe
Copy link
Member

flaeppe commented May 20, 2024

Equipment_ManyRelatedManager is a subclass of ManyRelatedManager and the default manager of your Equipment model.

The runtime names it ManyRelatedManager. But you can see that it's dynamically subclassed (normally by another manager) here:

https://github.com/django/django/blob/8f205acea94e93a463109e08814f78c09307f2b9/django/db/models/fields/related_descriptors.py#L1040

As long as your Establishment class is a subclass of models.Model, could perhaps a solution here be to change the through= to have a full lazy reference? e.g. "<app_label>. EquipmentEstablishmentMembership" Ref: #1802 (comment)

And then remove the explicit type annotation for the field as mypy should be able to infer the type itself.

class Establishment:
-	equipments: models.ManyToManyField[Equipment, EquipmentEstablishmentMembership] = models.ManyToManyField(
+	equipments = models.ManyToManyField(
	        Equipment,
-	        through="EquipmentEstablishmentMembership",
+	        through="<app_label>.EquipmentEstablishmentMembership",
	        blank=True,
	        related_name="establishments",
	    )

Additionally, 5.0.0 included an update to ManyRelatedManager to have 2 type parameters in #2026. If the type hinting is necessary/wanted for equipments_manager you probably want to change:

-equipments_manager: manager.ManyRelatedManager[Equipment]
+equipments_manager: manager.ManyRelatedManager[Equipment, EquipmentEstablishmentMembership]

@martinlehoux
Copy link
Contributor Author

Thanks @flaeppe for your input! I used the lazy reference and removed the type annotation and it works like a charm!

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

No branches or pull requests

2 participants