From e512196f2a2b40b2d42f3964b585ff024aa43c6f Mon Sep 17 00:00:00 2001 From: rafonseca Date: Mon, 6 May 2024 18:35:42 +0200 Subject: [PATCH] Allow single generic param for Field in ForeignKey --- django-stubs/db/models/fields/related.pyi | 2 +- .../typecheck/models/test_related_fields.yml | 55 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/django-stubs/db/models/fields/related.pyi b/django-stubs/db/models/fields/related.pyi index 3aef197ef..f07c11fc5 100644 --- a/django-stubs/db/models/fields/related.pyi +++ b/django-stubs/db/models/fields/related.pyi @@ -29,7 +29,7 @@ def resolve_relation(scope_model: type[Model], relation: str | type[Model]) -> s # __set__ value type _ST = TypeVar("_ST") # __get__ return type -_GT = TypeVar("_GT") +_GT = TypeVar("_GT", default=_ST) class RelatedField(FieldCacheMixin, Field[_ST, _GT]): one_to_many: bool diff --git a/tests/typecheck/models/test_related_fields.yml b/tests/typecheck/models/test_related_fields.yml index 3f6189f15..802a5a4ae 100644 --- a/tests/typecheck/models/test_related_fields.yml +++ b/tests/typecheck/models/test_related_fields.yml @@ -142,3 +142,58 @@ class Other(models.Model): field = models.ForeignKey(MyModel, related_name="others", on_delete=models.CASCADE) + + +- case: test_related_fields_with_two_generic_parameters + main: | + from myapp.models import Address, School, Student + reveal_type(Student().school) # N: Revealed type is "myapp.models.School" + reveal_type(Student().address) # N: Revealed type is "myapp.models.Address" + s = Student() + s.school = School() + s.address = Address() + installed_apps: + - myapp + files: + - path: myapp/__init__.py + - path: myapp/models.py + content: | + from django.db import models + + class School(models.Model): + pass + + class Address(models.Model): + pass + + class Student(models.Model): + school = models.ForeignKey["School","School"](to="School", on_delete=models.CASCADE) + address = models.OneToOneField["Address","Address"](to="Address", on_delete=models.CASCADE) + + +- case: test_related_fields_with_one_generic_parameter + expect_fail: True + main: | + from myapp.models import Address, School, Student + reveal_type(Student().school) # N: Revealed type is "myapp.models.School" + reveal_type(Student().address) # N: Revealed type is "myapp.models.Address" + s = Student() + s.school = School() + s.address = Address() + installed_apps: + - myapp + files: + - path: myapp/__init__.py + - path: myapp/models.py + content: | + from django.db import models + + class School(models.Model): + pass + + class Address(models.Model): + pass + + class Student(models.Model): + school = models.ForeignKey["School"](to="School", on_delete=models.CASCADE) + address = models.OneToOneField["Address"](to="Address", on_delete=models.CASCADE)