diff --git a/django-stubs/db/models/fields/related.pyi b/django-stubs/db/models/fields/related.pyi index f07c11fc5..0d812d590 100644 --- a/django-stubs/db/models/fields/related.pyi +++ b/django-stubs/db/models/fields/related.pyi @@ -27,9 +27,9 @@ RECURSIVE_RELATIONSHIP_CONSTANT: Literal["self"] def resolve_relation(scope_model: type[Model], relation: str | type[Model]) -> str | type[Model]: ... # __set__ value type -_ST = TypeVar("_ST") +_ST = TypeVar("_ST", contravariant=True) # __get__ return type -_GT = TypeVar("_GT", default=_ST) +_GT = TypeVar("_GT", covariant=True, default=_ST) class RelatedField(FieldCacheMixin, Field[_ST, _GT]): one_to_many: bool diff --git a/tests/typecheck/fields/test_related.yml b/tests/typecheck/fields/test_related.yml index 25c798adb..7d5db036b 100644 --- a/tests/typecheck/fields/test_related.yml +++ b/tests/typecheck/fields/test_related.yml @@ -86,6 +86,29 @@ related_name='books') publisher2 = models.ForeignKey(to=Publisher, related_name='books2', on_delete=models.CASCADE) +- case: foreign_key_subclass + main: | + from myapp.models import A + reveal_type(A.objects.get().b) # N: Revealed type is "myapp.models.B" + installed_apps: + - myapp + files: + - path: myapp/__init__.py + - path: myapp/models.py + content: | + from typing import TypeVar + from django.db import models + + _ST = TypeVar("_ST", contravariant=True) + _GT = TypeVar("_GT", covariant=True) + + class MyForeignKey(models.ForeignKey[_ST, _GT]): ... + + class B(models.Model): ... + + class A(models.Model): + b = models.ForeignKey(B, on_delete=models.CASCADE) + - case: to_parameter_as_string_with_application_name__model_imported main: | from myapp2.models import Book