[CASE test_queryset] from django.db import models class Blog(models.Model): name = models.CharField(max_length=100) created_at = models.DateTimeField() # QuerySet where second type argument is not specified shouldn't raise any errors class BlogQuerySet(models.QuerySet[Blog]): pass class Entry(models.Model): blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name="entries") title = models.CharField(max_length=100) # Test that second type argument gets filled automatically blog_qs: models.QuerySet[Blog] reveal_type(blog_qs) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog, main.Blog]' reveal_type(Blog.objects.in_bulk([1])) # E: Revealed type is 'builtins.dict[Any, main.Blog*]' reveal_type(Blog.objects.in_bulk()) # E: Revealed type is 'builtins.dict[Any, main.Blog*]' reveal_type(Blog.objects.in_bulk(['beatles_blog'], field_name='name')) # E: Revealed type is 'builtins.dict[Any, main.Blog*]' # When ANDing QuerySets, the left-side's _Row parameter is used reveal_type(Blog.objects.all() & Blog.objects.values()) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, main.Blog*]' reveal_type(Blog.objects.values() & Blog.objects.values()) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, builtins.dict*[builtins.str, Any]]' reveal_type(Blog.objects.values_list('id', 'name') & Blog.objects.values()) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, Tuple[builtins.int, builtins.str]]' reveal_type(Blog.objects.values_list('id', 'name', named=True) & Blog.objects.values()) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, Tuple[builtins.int, builtins.str, fallback=main.Row]]' reveal_type(Blog.objects.values_list('id', flat=True) & Blog.objects.values()) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, builtins.int*]' # .dates / .datetimes reveal_type(Blog.objects.dates("created_at", "day")) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, datetime.date]' reveal_type(Blog.objects.datetimes("created_at", "day")) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, datetime.datetime]' qs = Blog.objects.all() reveal_type(qs) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, main.Blog*]' reveal_type(qs.get(id=1)) # E: Revealed type is 'main.Blog*' reveal_type(iter(qs)) # E: Revealed type is 'typing.Iterator[main.Blog*]' reveal_type(qs.iterator()) # E: Revealed type is 'typing.Iterator[main.Blog*]' reveal_type(qs.first()) # E: Revealed type is 'Union[main.Blog*, None]' reveal_type(qs.earliest()) # E: Revealed type is 'main.Blog*' reveal_type(qs[0]) # E: Revealed type is 'main.Blog*' reveal_type(qs[:9]) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, main.Blog*]' reveal_type(qs.in_bulk()) # E: Revealed type is 'builtins.dict[Any, main.Blog*]' values_qs = Blog.objects.values() reveal_type(values_qs) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, builtins.dict[builtins.str, Any]]' reveal_type(values_qs.all()) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, builtins.dict*[builtins.str, Any]]' reveal_type(values_qs.get(id=1)) # E: Revealed type is 'builtins.dict*[builtins.str, Any]' reveal_type(iter(values_qs)) # E: Revealed type is 'typing.Iterator[builtins.dict*[builtins.str, Any]]' reveal_type(values_qs.iterator()) # E: Revealed type is 'typing.Iterator[builtins.dict*[builtins.str, Any]]' reveal_type(values_qs.first()) # E: Revealed type is 'Union[builtins.dict*[builtins.str, Any], None]' reveal_type(values_qs.earliest()) # E: Revealed type is 'builtins.dict*[builtins.str, Any]' reveal_type(values_qs[0]) # E: Revealed type is 'builtins.dict*[builtins.str, Any]' reveal_type(values_qs[:9]) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, builtins.dict*[builtins.str, Any]]' reveal_type(values_qs.in_bulk()) # E: Revealed type is 'builtins.dict[Any, main.Blog*]' values_list_qs = Blog.objects.values_list('id', 'name') reveal_type(values_list_qs) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, Tuple[builtins.int, builtins.str]]' reveal_type(values_list_qs.all()) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, Tuple[builtins.int, builtins.str]]' reveal_type(values_list_qs.get(id=1)) # E: Revealed type is 'Tuple[builtins.int, builtins.str]' reveal_type(iter(values_list_qs)) # E: Revealed type is 'typing.Iterator[Tuple[builtins.int, builtins.str]]' reveal_type(values_list_qs.iterator()) # E: Revealed type is 'typing.Iterator[Tuple[builtins.int, builtins.str]]' reveal_type(values_list_qs.first()) # E: Revealed type is 'Union[Tuple[builtins.int, builtins.str], None]' reveal_type(values_list_qs.earliest()) # E: Revealed type is 'Tuple[builtins.int, builtins.str]' reveal_type(values_list_qs[0]) # E: Revealed type is 'Tuple[builtins.int, builtins.str]' reveal_type(values_list_qs[:9]) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, Tuple[builtins.int, builtins.str]]' reveal_type(values_list_qs.in_bulk()) # E: Revealed type is 'builtins.dict[Any, main.Blog*]' flat_values_list_qs = Blog.objects.values_list('id', flat=True) reveal_type(flat_values_list_qs) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, builtins.int]' reveal_type(flat_values_list_qs.all()) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, builtins.int*]' reveal_type(flat_values_list_qs.get(id=1)) # E: Revealed type is 'builtins.int*' reveal_type(iter(flat_values_list_qs)) # E: Revealed type is 'typing.Iterator[builtins.int*]' reveal_type(flat_values_list_qs.iterator()) # E: Revealed type is 'typing.Iterator[builtins.int*]' reveal_type(flat_values_list_qs.first()) # E: Revealed type is 'Union[builtins.int*, None]' reveal_type(flat_values_list_qs.earliest()) # E: Revealed type is 'builtins.int*' reveal_type(flat_values_list_qs[0]) # E: Revealed type is 'builtins.int*' reveal_type(flat_values_list_qs[:9]) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, builtins.int*]' reveal_type(flat_values_list_qs.in_bulk()) # E: Revealed type is 'builtins.dict[Any, main.Blog*]' named_values_list_qs = Blog.objects.values_list('id', named=True) reveal_type(named_values_list_qs) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, Tuple[builtins.int, fallback=main.Row1]]' reveal_type(named_values_list_qs.all()) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, Tuple[builtins.int, fallback=main.Row1]]' reveal_type(named_values_list_qs.get(id=1)) # E: Revealed type is 'Tuple[builtins.int, fallback=main.Row1]' reveal_type(iter(named_values_list_qs)) # E: Revealed type is 'typing.Iterator[Tuple[builtins.int, fallback=main.Row1]]' reveal_type(named_values_list_qs.iterator()) # E: Revealed type is 'typing.Iterator[Tuple[builtins.int, fallback=main.Row1]]' reveal_type(named_values_list_qs.first()) # E: Revealed type is 'Union[Tuple[builtins.int, fallback=main.Row1], None]' reveal_type(named_values_list_qs.earliest()) # E: Revealed type is 'Tuple[builtins.int, fallback=main.Row1]' reveal_type(named_values_list_qs[0]) # E: Revealed type is 'Tuple[builtins.int, fallback=main.Row1]' reveal_type(named_values_list_qs[:9]) # E: Revealed type is 'django.db.models.query.QuerySet[main.Blog*, Tuple[builtins.int, fallback=main.Row1]]' reveal_type(named_values_list_qs.in_bulk()) # E: Revealed type is 'builtins.dict[Any, main.Blog*]' [out] [CASE test_queryset_values_list_custom_primary_key] from django.db import models class Blog(models.Model): primary_uuid = models.UUIDField(primary_key=True) class Entry(models.Model): blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name="entries") # Blog has a primary key field specified, so no automatic 'id' field is expected to exist reveal_type(Blog.objects.values_list('id', flat=True).get()) # E: Revealed type is 'Any' # Access Blog's pk (which is UUID field) reveal_type(Blog.objects.values_list('pk', flat=True).get()) # E: Revealed type is 'uuid.UUID*' # Accessing PK of model pointed to by foreign key reveal_type(Entry.objects.values_list('blog', flat=True).get()) # E: Revealed type is 'uuid.UUID*' # Alternative way of accessing PK of model pointed to by foreign key reveal_type(Entry.objects.values_list('blog_id', flat=True).get()) # E: Revealed type is 'uuid.UUID*' # Yet another (more explicit) way of accessing PK of related model reveal_type(Entry.objects.values_list('blog__pk', flat=True).get()) # E: Revealed type is 'uuid.UUID*' # Blog has a primary key field specified, so no automatic 'id' field is expected to exist reveal_type(Entry.objects.values_list('blog__id', flat=True).get()) # E: Revealed type is 'Any' [CASE test_queryset_values_list] from django.db import models class Blog(models.Model): name = models.CharField(max_length=100) created_at = models.DateTimeField() class Entry(models.Model): blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name="entries") nullable_blog = models.ForeignKey(Blog, on_delete=models.CASCADE, related_name="+", null=True) blog_with_related_query_name = models.ForeignKey(Blog, on_delete=models.CASCADE, related_query_name="my_related_query_name") title = models.CharField(max_length=100) class BlogChild(Blog): child_field = models.CharField(max_length=100) # Emulate at type-check time the errors that Django reports Blog.objects.values_list('id', flat=True, named=True) # E: 'flat' and 'named' can't be used together. Blog.objects.values_list('id', 'created_at', flat=True) # E: 'flat' is not valid when values_list is called with more than one field. # values_list where parameter types are all known reveal_type(Blog.objects.values_list('id', 'created_at').get()) # E: Revealed type is 'Tuple[builtins.int, datetime.datetime]' tup = Blog.objects.values_list('id', 'created_at').get() reveal_type(tup[0]) # E: Revealed type is 'builtins.int' reveal_type(tup[1]) # E: Revealed type is 'datetime.datetime' tup[2] # E: Tuple index out of range # values_list returning namedtuple reveal_type(Blog.objects.values_list('id', 'created_at', named=True).get()) # E: Revealed type is 'Tuple[builtins.int, datetime.datetime, fallback=main.Row]' # Invalid lookups produce Any type rather than giving errors. reveal_type(Blog.objects.values_list('id', 'invalid_lookup').get()) # E: Revealed type is 'Tuple[builtins.int, Any]' reveal_type(Blog.objects.values_list('entries_id', flat=True).get()) # E: Revealed type is 'Any' reveal_type(Blog.objects.values_list('entries__foo', flat=True).get()) # E: Revealed type is 'Any' reveal_type(Blog.objects.values_list('+', flat=True).get()) # E: Revealed type is 'Any' # Foreign key reveal_type(Entry.objects.values_list('blog', flat=True).get()) # E: Revealed type is 'builtins.int*' reveal_type(Entry.objects.values_list('blog__id', flat=True).get()) # E: Revealed type is 'builtins.int*' reveal_type(Entry.objects.values_list('blog__pk', flat=True).get()) # E: Revealed type is 'builtins.int*' reveal_type(Entry.objects.values_list('blog_id', flat=True).get()) # E: Revealed type is 'builtins.int*' # Foreign key (nullable=True) reveal_type(Entry.objects.values_list('nullable_blog', flat=True).get()) # E: Revealed type is 'Union[builtins.int, None]' reveal_type(Entry.objects.values_list('nullable_blog_id', flat=True).get()) # E: Revealed type is 'Union[builtins.int, None]' reveal_type(Entry.objects.values_list('nullable_blog__id', flat=True).get()) # E: Revealed type is 'Union[builtins.int, None]' reveal_type(Entry.objects.values_list('nullable_blog__pk', flat=True).get()) # E: Revealed type is 'Union[builtins.int, None]' # Reverse relation of ForeignKey reveal_type(Blog.objects.values_list('entries', flat=True).get()) # E: Revealed type is 'Union[builtins.int, None]' reveal_type(Blog.objects.values_list('entries__id', flat=True).get()) # E: Revealed type is 'Union[builtins.int, None]' reveal_type(Blog.objects.values_list('entries__title', flat=True).get()) # E: Revealed type is 'Union[builtins.str, None]' # Reverse relation of ForeignKey (with related_query_name set) reveal_type(Blog.objects.values_list('my_related_query_name__id', flat=True).get()) # E: Revealed type is 'Union[builtins.int, None]' # Basic inheritance reveal_type(BlogChild.objects.values_list('id', 'created_at', 'child_field').get()) # E: Revealed type is 'Tuple[builtins.int, datetime.datetime, builtins.str]' [CASE test_queryset_values_list_and_values_behavior_with_no_fields_specified_and_accessing_unknown_attributes] from django.db import models class Blog(models.Model): name = models.CharField(max_length=100) created_at = models.DateTimeField() row_named = Blog.objects.values_list('id', 'created_at', named=True).get() reveal_type(row_named.id) # E: Revealed type is 'builtins.int' reveal_type(row_named.created_at) # E: Revealed type is 'datetime.datetime' row_named.non_existent_field # E: "Row" has no attribute "non_existent_field" # When no fields are specified, fallback to Any row_named_no_fields = Blog.objects.values_list(named=True).get() reveal_type(row_named_no_fields) # E: Revealed type is 'Tuple[, fallback=django._NamedTupleAnyAttr]' # Don't complain about access to any attribute for now reveal_type(row_named_no_fields.non_existent_field) # E: Revealed type is 'Any' row_named_no_fields.non_existent_field = 1 # It should still behave like a NamedTuple reveal_type(row_named_no_fields._asdict()) # E: Revealed type is 'builtins.dict[builtins.str, Any]' dict_row = Blog.objects.values('id', 'created_at').get() reveal_type(dict_row["id"]) # E: Revealed type is 'builtins.int' reveal_type(dict_row["created_at"]) # E: Revealed type is 'datetime.datetime' dict_row["non_existent_field"] # E: 'non_existent_field' is not a valid TypedDict key; expected one of ('id', 'created_at') dict_row.pop('created_at') dict_row.pop('non_existent_field') # E: 'non_existent_field' is not a valid TypedDict key; expected one of ('id', 'created_at') row_dict_no_fields = Blog.objects.values().get() reveal_type(row_dict_no_fields) # E: Revealed type is 'builtins.dict*[builtins.str, Any]' reveal_type(row_dict_no_fields["non_existent_field"]) # E: Revealed type is 'Any' [CASE values_with_annotate_inside_the_expressions] from django.db import models from django.db.models.functions import Lower, Upper class Publisher(models.Model): pass class Book(models.Model): name = models.CharField(max_length=100) publisher = models.ForeignKey(to=Publisher, on_delete=models.CASCADE, related_name='books') reveal_type(Publisher().books.values('name', lower_name=Lower('name'), upper_name=Upper('name'))) # E: Revealed type is 'django.db.models.query.QuerySet[main.Book*, TypedDict({'name'?: builtins.str, 'lower_name'?: Any, 'upper_name'?: Any})]' [CASE values_and_values_list_some_dynamic_fields] from django.db import models class Publisher(models.Model): pass class Book(models.Model): name = models.CharField(max_length=100) publisher = models.ForeignKey(to=Publisher, on_delete=models.CASCADE, related_name='books') some_dynamic_field = 'publisher' # Correct Tuple field types should be filled in when string literal is used, while Any is used for dynamic fields reveal_type(Publisher().books.values_list('name', some_dynamic_field)) # E: Revealed type is 'django.db.models.query.QuerySet[main.Book*, Tuple[builtins.str, Any]]' # Flat with dynamic fields (there is only 1), means of course Any reveal_type(Publisher().books.values_list(some_dynamic_field, flat=True)) # E: Revealed type is 'django.db.models.query.QuerySet[main.Book*, Any]' # A NamedTuple with a fallback to Any could be implemented, but for now that's unsupported, so all # fields on the NamedTuple are Any for now reveal_type(Publisher().books.values_list('name', some_dynamic_field, named=True).name) # E: Revealed type is 'Any' # A TypedDict with a fallback to Any could be implemented, but for now that's unsupported, # so an ordinary Dict is used for now. reveal_type(Publisher().books.values(some_dynamic_field, 'name')) # E: Revealed type is 'django.db.models.query.QuerySet[main.Book*, builtins.dict[builtins.str, Any]]'