From f7958eaf7b8daf6f6451fe7da43acef8269f47df Mon Sep 17 00:00:00 2001 From: Noelle Leigh <5957867+noelleleigh@users.noreply.github.com> Date: Thu, 8 Aug 2024 07:25:00 -0400 Subject: [PATCH] contrib/admin/options: Improve types Improve the type hints for `BaseModelAdmin`, `ModelAdmin`, and `InlineModelAdmin` by: 1. Removing private method definitions 2. Use the `_ModelT` generic variable more 3. Make `Any` return types more specific It think the highest value change here is `ModelAdmin.get_form`, which is what prompted me to make these changes in the fist place. --- django-stubs/contrib/admin/options.pyi | 93 ++++++++++++++++---------- 1 file changed, 59 insertions(+), 34 deletions(-) diff --git a/django-stubs/contrib/admin/options.pyi b/django-stubs/contrib/admin/options.pyi index 193ca1ea9..72abb8247 100644 --- a/django-stubs/contrib/admin/options.pyi +++ b/django-stubs/contrib/admin/options.pyi @@ -4,6 +4,7 @@ from typing import Any, Generic, Iterable, TypeVar from typing_extensions import Literal, TypedDict from django.contrib.admin.filters import ListFilter +from django.contrib.admin.helpers import ActionForm from django.contrib.admin.models import LogEntry from django.contrib.admin.sites import AdminSite from django.contrib.admin.views.main import ChangeList @@ -20,7 +21,9 @@ from django.forms.fields import TypedChoiceField from django.forms.forms import BaseForm from django.forms.models import ( BaseInlineFormSet, + BaseModelFormSet, ModelChoiceField, + ModelForm, ModelMultipleChoiceField, ) from django.forms.widgets import Media @@ -81,8 +84,8 @@ class BaseModelAdmin(Generic[_ModelT]): prepopulated_fields: Mapping[str, Sequence[str]] = ... formfield_overrides: Mapping[type[Field[Any, Any]], Mapping[str, Any]] = ... readonly_fields: Sequence[str | Callable[[_ModelT], Any]] = ... - ordering: Sequence[str] = ... - sortable_by: Sequence[str] = ... + ordering: Sequence[str] | None = ... + sortable_by: Sequence[str] | None = ... view_on_site: bool = ... show_full_result_count: bool = ... checks_class: Any = ... @@ -105,10 +108,12 @@ class BaseModelAdmin(Generic[_ModelT]): request: HttpRequest | None, **kwargs: Any ) -> ModelMultipleChoiceField: ... - def get_autocomplete_fields(self, request: HttpRequest) -> tuple[Any, ...]: ... + def get_autocomplete_fields(self, request: HttpRequest) -> Sequence[str]: ... def get_view_on_site_url(self, obj: _ModelT | None = ...) -> str | None: ... def get_empty_value_display(self) -> SafeText: ... - def get_exclude(self, request: HttpRequest, obj: _ModelT | None = ...) -> Any: ... + def get_exclude( + self, request: HttpRequest, obj: _ModelT | None = ... + ) -> Sequence[str]: ... def get_fields( self, request: HttpRequest, obj: _ModelT | None = ... ) -> Sequence[Callable[..., Any] | str]: ... @@ -122,7 +127,7 @@ class BaseModelAdmin(Generic[_ModelT]): def get_prepopulated_fields( self, request: HttpRequest, obj: _ModelT | None = ... ) -> dict[str, tuple[str]]: ... - def get_queryset(self, request: HttpRequest) -> QuerySet[Any]: ... + def get_queryset(self, request: HttpRequest) -> QuerySet[_ModelT]: ... def get_sortable_by( self, request: HttpRequest ) -> list[Callable[..., Any]] | list[str] | tuple[Any, ...]: ... @@ -170,12 +175,12 @@ class ModelAdmin(BaseModelAdmin[_ModelT]): Callable[[ModelAdmin[Any], HttpRequest, QuerySet[Any]], HttpResponse | None] | str ] | None = ... - action_form: Any = ... + action_form: type[ActionForm] = ... actions_on_top: bool = ... actions_on_bottom: bool = ... actions_selection_counter: bool = ... model: type[_ModelT] = ... - opts: Options[Any] = ... + opts: Options[_ModelT] = ... admin_site: AdminSite = ... def __init__(self, model: type[_ModelT], admin_site: AdminSite | None) -> None: ... def get_inline_instances( @@ -188,8 +193,12 @@ class ModelAdmin(BaseModelAdmin[_ModelT]): def media(self) -> Media: ... def get_model_perms(self, request: HttpRequest) -> dict[str, bool]: ... def get_form( - self, request: Any, obj: _ModelT | None = ..., change: bool = ..., **kwargs: Any - ) -> Any: ... + self, + request: HttpRequest, + obj: _ModelT | None = ..., + change: bool = ..., + **kwargs: Any + ) -> type[ModelForm]: ... def get_changelist( self, request: HttpRequest, **kwargs: Any ) -> type[ChangeList]: ... @@ -197,15 +206,19 @@ class ModelAdmin(BaseModelAdmin[_ModelT]): def get_object( self, request: HttpRequest, object_id: str, from_field: None = ... ) -> _ModelT | None: ... - def get_changelist_form(self, request: Any, **kwargs: Any) -> Any: ... - def get_changelist_formset(self, request: Any, **kwargs: Any) -> Any: ... + def get_changelist_form( + self, request: HttpRequest, **kwargs: Any + ) -> type[ModelForm]: ... + def get_changelist_formset( + self, request: HttpRequest, **kwargs: Any + ) -> type[BaseModelFormSet]: ... def get_formsets_with_inlines( self, request: HttpRequest, obj: _ModelT | None = ... ) -> Iterator[Any]: ... def get_paginator( self, request: HttpRequest, - queryset: QuerySet[Any], + queryset: QuerySet[_ModelT], per_page: int, orphans: int = ..., allow_empty_first_page: bool = ..., @@ -238,12 +251,6 @@ class ModelAdmin(BaseModelAdmin[_ModelT]): self, request: HttpRequest, queryset: QuerySet[Any], search_term: str ) -> tuple[QuerySet[Any], bool]: ... def get_preserved_filters(self, request: HttpRequest) -> str: ... - def _get_edited_object_pks( - self, request: HttpRequest, prefix: str - ) -> list[str]: ... - def _get_list_editable_queryset( - self, request: HttpRequest, prefix: str - ) -> QuerySet[Any]: ... def construct_change_message( self, request: HttpRequest, @@ -259,29 +266,39 @@ class ModelAdmin(BaseModelAdmin[_ModelT]): extra_tags: str = ..., fail_silently: bool = ..., ) -> None: ... - def save_form(self, request: Any, form: Any, change: Any) -> Any: ... + def save_form( + self, request: HttpRequest, form: ModelForm, change: bool + ) -> _ModelT: ... def save_model( - self, request: Any, obj: _ModelT, form: Any, change: Any + self, request: HttpRequest, obj: _ModelT, form: ModelForm, change: bool ) -> None: ... def delete_model(self, request: HttpRequest, obj: _ModelT) -> None: ... def delete_queryset( - self, request: HttpRequest, queryset: QuerySet[Any] + self, request: HttpRequest, queryset: QuerySet[_ModelT] ) -> None: ... def save_formset( - self, request: Any, form: Any, formset: Any, change: Any + self, + request: HttpRequest, + form: ModelForm, + formset: BaseModelFormSet, + change: bool, ) -> None: ... def save_related( - self, request: Any, form: Any, formsets: Any, change: Any + self, + request: HttpRequest, + form: ModelForm, + formsets: BaseModelFormSet, + change: bool, ) -> None: ... def render_change_form( self, - request: Any, - context: Any, + request: HttpRequest, + context: Mapping[str, Any], add: bool = ..., change: bool = ..., form_url: str = ..., obj: _ModelT | None = ..., - ) -> Any: ... + ) -> TemplateResponse: ... def response_add( self, request: HttpRequest, obj: _ModelT, post_url_continue: str | None = ... ) -> HttpResponse: ... @@ -293,12 +310,14 @@ class ModelAdmin(BaseModelAdmin[_ModelT]): self, request: HttpRequest, obj: _ModelT ) -> HttpResponseRedirect: ... def response_action( - self, request: HttpRequest, queryset: QuerySet[Any] + self, request: HttpRequest, queryset: QuerySet[_ModelT] ) -> HttpResponseBase | None: ... def response_delete( self, request: HttpRequest, obj_display: str, obj_id: int ) -> HttpResponse: ... - def render_delete_form(self, request: Any, context: Any) -> Any: ... + def render_delete_form( + self, request: HttpRequest, context: Mapping[str, Any] + ) -> TemplateResponse: ... def get_inline_formsets( self, request: HttpRequest, @@ -313,7 +332,7 @@ class ModelAdmin(BaseModelAdmin[_ModelT]): object_id: str | None = ..., form_url: str = ..., extra_context: dict[str, bool] | None = ..., - ) -> Any: ... + ) -> TemplateResponse: ... def autocomplete_view(self, request: HttpRequest) -> JsonResponse: ... def add_view( self, request: HttpRequest, form_url: str = ..., extra_context: None = ... @@ -332,10 +351,16 @@ class ModelAdmin(BaseModelAdmin[_ModelT]): self, objs: QuerySet[Any], request: HttpRequest ) -> tuple[list[Any], dict[Any, Any], set[Any], list[Any]]: ... def delete_view( - self, request: HttpRequest, object_id: str, extra_context: None = ... - ) -> Any: ... + self, + request: HttpRequest, + object_id: str, + extra_context: dict[str, str] | None = ..., + ) -> HttpResponse: ... def history_view( - self, request: HttpRequest, object_id: str, extra_context: None = ... + self, + request: HttpRequest, + object_id: str, + extra_context: dict[str, str] | None = ..., ) -> HttpResponse: ... def get_formset_kwargs( self, @@ -377,8 +402,8 @@ class InlineModelAdmin(BaseModelAdmin[_ModelT]): self, request: HttpRequest, obj: _ModelT | None = ..., **kwargs: Any ) -> int | None: ... def get_formset( - self, request: Any, obj: _ModelT | None = ..., **kwargs: Any - ) -> Any: ... + self, request: HttpRequest, obj: _ModelT | None = ..., **kwargs: Any + ) -> type[BaseInlineFormSet]: ... class StackedInline(InlineModelAdmin[_ModelT]): ... class TabularInline(InlineModelAdmin[_ModelT]): ...