Skip to content

Commit

Permalink
Improve get_context_object_name on SingleObjectMixin and `Multipl…
Browse files Browse the repository at this point in the history
…eObjectMixin` (#2298)
  • Loading branch information
flaeppe authored Jul 31, 2024
1 parent 9c156a0 commit b76f9f4
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 7 deletions.
7 changes: 5 additions & 2 deletions django-stubs/views/generic/detail.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Any, Generic, TypeVar
from typing import Any, Generic, TypeVar, overload

from django.db import models
from django.http import HttpRequest, HttpResponse
Expand All @@ -17,7 +17,10 @@ class SingleObjectMixin(Generic[_M], ContextMixin):
def get_object(self, queryset: models.query.QuerySet[_M] | None = ...) -> _M: ...
def get_queryset(self) -> models.query.QuerySet[_M]: ...
def get_slug_field(self) -> str: ...
def get_context_object_name(self, obj: _M) -> str | None: ...
@overload
def get_context_object_name(self, obj: _M) -> str: ...
@overload
def get_context_object_name(self, obj: Any) -> str | None: ...

class BaseDetailView(SingleObjectMixin[_M], View):
object: _M
Expand Down
14 changes: 11 additions & 3 deletions django-stubs/views/generic/list.pyi
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
from collections.abc import Sequence
from typing import Any, Generic, TypeVar
from typing import Any, Generic, Protocol, TypeVar, overload, type_check_only

from django.core.paginator import Page, Paginator, _SupportsPagination
from django.db.models import Model, QuerySet
from django.http import HttpRequest, HttpResponse
from django.views.generic.base import ContextMixin, TemplateResponseMixin, View

_M = TypeVar("_M", bound=Model, covariant=True)
_M = TypeVar("_M", bound=Model)

@type_check_only
class _HasModel(Protocol):
@property
def model(self) -> type[Model]: ...

class MultipleObjectMixin(Generic[_M], ContextMixin):
allow_empty: bool
Expand Down Expand Up @@ -34,7 +39,10 @@ class MultipleObjectMixin(Generic[_M], ContextMixin):
) -> Paginator: ...
def get_paginate_orphans(self) -> int: ...
def get_allow_empty(self) -> bool: ...
def get_context_object_name(self, object_list: _SupportsPagination[_M]) -> str | None: ...
@overload
def get_context_object_name(self, object_list: _HasModel) -> str: ...
@overload
def get_context_object_name(self, object_list: Any) -> str | None: ...
def get_context_data(
self, *, object_list: _SupportsPagination[_M] | None = ..., **kwargs: Any
) -> dict[str, Any]: ...
Expand Down
30 changes: 30 additions & 0 deletions tests/assert_type/views/generic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from typing import Optional, Type

from django.db import models
from django.views.generic.detail import SingleObjectMixin
from django.views.generic.list import ListView
from typing_extensions import assert_type


class MyModel(models.Model): ...


class MyDetailView(SingleObjectMixin[MyModel]): ...


detail_view = MyDetailView()
assert_type(detail_view.model, Type[MyModel])
assert_type(detail_view.queryset, Optional[models.QuerySet[MyModel, MyModel]])
assert_type(detail_view.get_context_object_name(MyModel()), str)
assert_type(detail_view.get_context_object_name(1), Optional[str])


class MyListView(ListView[MyModel]): ...


list_view = MyListView()
assert_type(list_view.model, Optional[Type[MyModel]])
assert_type(list_view.queryset, Optional[models.QuerySet[MyModel, MyModel]])
assert_type(list_view.get_context_object_name(models.QuerySet[MyModel]()), str)
assert_type(list_view.get_context_object_name(MyModel()), Optional[str])
assert_type(list_view.get_context_object_name(1), Optional[str])
4 changes: 2 additions & 2 deletions tests/typecheck/views/generic/test_detail.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@
def get_queryset(self) -> QuerySet[MyModel]:
self.get_object(super().get_queryset())
return super().get_queryset()
custom_settings: |
INSTALLED_APPS = ('myapp',)
installed_apps:
- myapp
files:
- path: myapp/__init__.py
- path: myapp/models.py
Expand Down

0 comments on commit b76f9f4

Please sign in to comment.