Skip to content

Commit 3f9b3c8

Browse files
authored
5.0: Update django.contrib.admin (#2004)
* Remove unnecessary overrides in `django.contrib.admin.filters` * Fix allowlist items for `django.contrib.admin.filters` * Improve typing further in `django.contrib.admin.filters` * 5.0: Update `django.contrib.admin`
1 parent efcb200 commit 3f9b3c8

File tree

9 files changed

+65
-90
lines changed

9 files changed

+65
-90
lines changed

django-stubs/contrib/admin/__init__.pyi

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ from .filters import SimpleListFilter as SimpleListFilter
1515
from .options import HORIZONTAL as HORIZONTAL
1616
from .options import VERTICAL as VERTICAL
1717
from .options import ModelAdmin as ModelAdmin
18+
from .options import ShowFacets as ShowFacets
1819
from .options import StackedInline as StackedInline
1920
from .options import TabularInline as TabularInline
2021
from .sites import AdminSite as AdminSite

django-stubs/contrib/admin/exceptions.pyi

+2
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ from django.core.exceptions import SuspiciousOperation
22

33
class DisallowedModelAdminLookup(SuspiciousOperation): ...
44
class DisallowedModelAdminToField(SuspiciousOperation): ...
5+
class AlreadyRegistered(Exception): ...
6+
class NotRegistered(Exception): ...
+54-49
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,54 @@
11
from collections.abc import Callable, Iterable, Iterator
2-
from typing import Any
2+
from datetime import date, datetime
3+
from typing import Any, ClassVar
34

45
from django.contrib.admin.options import ModelAdmin
6+
from django.contrib.admin.views.main import ChangeList
7+
from django.db.models.aggregates import Count
58
from django.db.models.base import Model
69
from django.db.models.fields import Field
710
from django.db.models.fields.related import RelatedField
811
from django.db.models.query import QuerySet
12+
from django.db.models.query_utils import Q
913
from django.http.request import HttpRequest
14+
from django.utils.datastructures import _ListOrTuple
1015
from django.utils.functional import _StrOrPromise
16+
from django.utils.safestring import SafeString
17+
from typing_extensions import TypedDict
18+
19+
class _ListFilterChoices(TypedDict):
20+
selected: bool
21+
query_string: str
22+
display: _StrOrPromise
1123

1224
class ListFilter:
1325
title: _StrOrPromise | None
1426
template: str
15-
used_parameters: Any
27+
request: HttpRequest
28+
used_parameters: dict[str, bool | datetime | str]
1629
def __init__(
1730
self, request: HttpRequest, params: dict[str, str], model: type[Model], model_admin: ModelAdmin
1831
) -> None: ...
1932
def has_output(self) -> bool: ...
20-
def choices(self, changelist: Any) -> Iterator[dict[str, Any]]: ...
33+
def choices(self, changelist: ChangeList) -> Iterator[_ListFilterChoices]: ...
2134
def queryset(self, request: HttpRequest, queryset: QuerySet) -> QuerySet | None: ...
2235
def expected_parameters(self) -> list[str | None]: ...
2336

24-
class SimpleListFilter(ListFilter):
37+
class FacetsMixin:
38+
def get_facet_counts(self, pk_attname: str, filtered_qs: QuerySet[Model]) -> dict[str, Count]: ...
39+
def get_facet_queryset(self, changelist: ChangeList) -> dict[str, int]: ...
40+
41+
class SimpleListFilter(FacetsMixin, ListFilter):
2542
parameter_name: str | None
26-
lookup_choices: Any
43+
lookup_choices: list[tuple[str, _StrOrPromise]]
2744
def value(self) -> str | None: ...
28-
def lookups(self, request: HttpRequest, model_admin: ModelAdmin) -> Iterable[tuple[Any, str]] | None: ...
29-
def choices(self, changelist: Any) -> Iterator[dict[str, Any]]: ...
45+
def lookups(self, request: HttpRequest, model_admin: ModelAdmin) -> Iterable[tuple[str, _StrOrPromise]] | None: ...
3046

31-
class FieldListFilter(ListFilter):
47+
class FieldListFilter(FacetsMixin, ListFilter):
48+
list_separator: ClassVar[str]
3249
field: Field
3350
field_path: str
34-
title: str
51+
title: _StrOrPromise
3552
def __init__(
3653
self,
3754
field: Field,
@@ -42,7 +59,9 @@ class FieldListFilter(ListFilter):
4259
field_path: str,
4360
) -> None: ...
4461
@classmethod
45-
def register(cls, test: Callable, list_filter_class: type[FieldListFilter], take_priority: bool = ...) -> None: ...
62+
def register(
63+
cls, test: Callable[[Field], Any], list_filter_class: type[FieldListFilter], take_priority: bool = ...
64+
) -> None: ...
4665
@classmethod
4766
def create(
4867
cls,
@@ -55,67 +74,53 @@ class FieldListFilter(ListFilter):
5574
) -> FieldListFilter: ...
5675

5776
class RelatedFieldListFilter(FieldListFilter):
58-
used_parameters: dict[Any, Any]
5977
lookup_kwarg: str
6078
lookup_kwarg_isnull: str
61-
lookup_val: Any
62-
lookup_val_isnull: Any
63-
lookup_choices: Any
64-
lookup_title: str
65-
title: str
66-
empty_value_display: Any
79+
lookup_val: str | None
80+
lookup_val_isnull: str | None
81+
lookup_choices: list[tuple[str, _StrOrPromise]]
82+
lookup_title: _StrOrPromise
83+
empty_value_display: SafeString
6784
@property
6885
def include_empty_choice(self) -> bool: ...
86+
def field_admin_ordering(
87+
self, field: RelatedField, request: HttpRequest, model_admin: ModelAdmin
88+
) -> _ListOrTuple[str]: ...
6989
def field_choices(
7090
self, field: RelatedField, request: HttpRequest, model_admin: ModelAdmin
71-
) -> list[tuple[str, str]]: ...
72-
def choices(self, changelist: Any) -> Iterator[dict[str, Any]]: ...
91+
) -> list[tuple[str, _StrOrPromise]]: ...
7392

7493
class BooleanFieldListFilter(FieldListFilter):
7594
lookup_kwarg: str
7695
lookup_kwarg2: str
77-
lookup_val: Any
78-
lookup_val2: Any
79-
def choices(self, changelist: Any) -> Iterator[dict[str, Any]]: ...
96+
lookup_val: str | None
97+
lookup_val2: str | None
8098

8199
class ChoicesFieldListFilter(FieldListFilter):
82-
title: str
83-
used_parameters: dict[Any, Any]
84100
lookup_kwarg: str
85101
lookup_kwarg_isnull: str
86-
lookup_val: Any
87-
lookup_val_isnull: Any
88-
def choices(self, changelist: Any) -> Iterator[dict[str, Any]]: ...
102+
lookup_val: str | None
103+
lookup_val_isnull: str | None
89104

90105
class DateFieldListFilter(FieldListFilter):
91-
field_generic: Any
92-
date_params: Any
93-
lookup_kwarg_since: Any
94-
lookup_kwarg_until: Any
95-
links: Any
96-
lookup_kwarg_isnull: Any
97-
def choices(self, changelist: Any) -> Iterator[dict[str, Any]]: ...
106+
field_generic: str
107+
date_params: dict[str, str]
108+
lookup_kwarg_since: str
109+
lookup_kwarg_until: str
110+
links: tuple[tuple[_StrOrPromise, dict[str, bool | date | datetime]], ...]
111+
lookup_kwarg_isnull: str
98112

99113
class AllValuesFieldListFilter(FieldListFilter):
100-
title: str
101-
used_parameters: dict[Any, Any]
102114
lookup_kwarg: str
103115
lookup_kwarg_isnull: str
104-
lookup_val: Any
105-
lookup_val_isnull: Any
106-
empty_value_display: str
116+
lookup_val: str | None
117+
lookup_val_isnull: str | None
118+
empty_value_display: SafeString
107119
lookup_choices: QuerySet
108-
def choices(self, changelist: Any) -> Iterator[dict[str, Any]]: ...
109120

110-
class RelatedOnlyFieldListFilter(RelatedFieldListFilter):
111-
lookup_kwarg: str
112-
lookup_kwarg_isnull: str
113-
lookup_val: Any
114-
lookup_val_isnull: Any
115-
title: str
116-
used_parameters: dict[Any, Any]
121+
class RelatedOnlyFieldListFilter(RelatedFieldListFilter): ...
117122

118123
class EmptyFieldListFilter(FieldListFilter):
119124
lookup_kwarg: str
120-
lookup_val: Any
121-
def choices(self, changelist: Any) -> Iterator[dict[str, Any]]: ...
125+
lookup_val: str | None
126+
def get_lookup_condition(self) -> Q: ...

django-stubs/contrib/admin/options.pyi

+1
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ from typing_extensions import TypeAlias, TypedDict
3838

3939
IS_POPUP_VAR: str
4040
TO_FIELD_VAR: str
41+
IS_FACETS_VAR: str
4142
HORIZONTAL: Literal[1]
4243
VERTICAL: Literal[2]
4344

django-stubs/contrib/admin/sites.pyi

-3
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ else:
2828
_ViewType = TypeVar("_ViewType", bound=Callable[..., HttpResponse])
2929
_ActionCallback: TypeAlias = Callable[[ModelAdmin, HttpRequest, QuerySet], TemplateResponse | None]
3030

31-
class AlreadyRegistered(Exception): ...
32-
class NotRegistered(Exception): ...
33-
3431
class AdminSite:
3532
site_title: _StrOrPromise
3633
site_header: _StrOrPromise

django-stubs/contrib/admin/utils.pyi

+6-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ from django.db.models.deletion import Collector
1313
from django.db.models.fields import Field, reverse_related
1414
from django.db.models.options import Options
1515
from django.db.models.query import QuerySet
16+
from django.db.models.query_utils import Q
1617
from django.forms.forms import BaseForm
1718
from django.forms.formsets import BaseFormSet
1819
from django.http.request import HttpRequest
@@ -24,7 +25,11 @@ _T = TypeVar("_T")
2425
class FieldIsAForeignKeyColumnName(Exception): ...
2526

2627
def lookup_spawns_duplicates(opts: Options, lookup_path: str) -> bool: ...
27-
def prepare_lookup_value(key: str, value: datetime.datetime | str) -> bool | datetime.datetime | str: ...
28+
def get_last_value_from_parameters(parameters: dict[str, list[str] | str], key: str) -> str | None: ...
29+
def prepare_lookup_value(
30+
key: str, value: list[bool | datetime.datetime | str] | datetime.datetime | str, separator: str
31+
) -> list[bool | datetime.datetime | str] | bool | datetime.datetime | str: ...
32+
def build_q_object_from_lookup_parameters(parameters: dict[str, list[str]]) -> Q: ...
2833
def quote(s: int | str | UUID) -> str: ...
2934
def unquote(s: str) -> str: ...
3035
def flatten(fields: Any) -> list[Callable | str]: ...

django-stubs/contrib/admin/views/main.pyi

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class ChangeList:
7777
def get_ordering_field(self, field_name: Callable | str) -> Expression | str | None: ...
7878
def get_ordering(self, request: HttpRequest, queryset: QuerySet) -> list[Expression | str]: ...
7979
def get_ordering_field_columns(self) -> dict[int, Literal["desc", "asc"]]: ...
80-
def get_queryset(self, request: HttpRequest) -> QuerySet: ...
80+
def get_queryset(self, request: HttpRequest, exclude_parameters: list[str | None] | None = ...) -> QuerySet: ...
8181
filter_specs: list[ListFilter]
8282
has_filters: bool
8383
has_active_filters: bool

scripts/stubtest/allowlist_todo.txt

-12
Original file line numberDiff line numberDiff line change
@@ -10,31 +10,19 @@ django.conf.STATICFILES_STORAGE_DEPRECATED_MSG
1010
django.conf.global_settings.gettext_noop
1111
django.conf.urls.IncludedURLConf
1212
django.conf.urls.url
13-
django.contrib.admin.AllValuesFieldListFilter.title
14-
django.contrib.admin.ChoicesFieldListFilter.title
15-
django.contrib.admin.FieldListFilter.list_separator
1613
django.contrib.admin.FieldListFilter.title
1714
django.contrib.admin.ModelAdmin
1815
django.contrib.admin.ModelAdmin.log_addition
1916
django.contrib.admin.ModelAdmin.log_change
2017
django.contrib.admin.ModelAdmin.log_deletion
21-
django.contrib.admin.RelatedFieldListFilter.field_admin_ordering
22-
django.contrib.admin.RelatedFieldListFilter.title
23-
django.contrib.admin.RelatedOnlyFieldListFilter.title
2418
django.contrib.admin.StackedInline
2519
django.contrib.admin.TabularInline
2620
django.contrib.admin.action
2721
django.contrib.admin.apps.AdminConfig.default
2822
django.contrib.admin.decorators.action
2923
django.contrib.admin.decorators.display
3024
django.contrib.admin.display
31-
django.contrib.admin.filters.AllValuesFieldListFilter.title
32-
django.contrib.admin.filters.ChoicesFieldListFilter.title
33-
django.contrib.admin.filters.FieldListFilter.list_separator
3425
django.contrib.admin.filters.FieldListFilter.title
35-
django.contrib.admin.filters.RelatedFieldListFilter.field_admin_ordering
36-
django.contrib.admin.filters.RelatedFieldListFilter.title
37-
django.contrib.admin.filters.RelatedOnlyFieldListFilter.title
3826
django.contrib.admin.forms.AdminAuthenticationForm
3927
django.contrib.admin.forms.AdminPasswordChangeForm
4028
django.contrib.admin.helpers.ActionForm

scripts/stubtest/allowlist_todo_django50.txt

-24
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,6 @@
22
# Only discrepancies that appeared after Django 4.2 -> 5.0 update.
33
# Unsorted: there are real problems and things we can really ignore.
44

5-
django.contrib.admin.AllValuesFieldListFilter.get_facet_counts
6-
django.contrib.admin.BooleanFieldListFilter.get_facet_counts
7-
django.contrib.admin.ChoicesFieldListFilter.get_facet_counts
8-
django.contrib.admin.DateFieldListFilter.get_facet_counts
9-
django.contrib.admin.EmptyFieldListFilter.get_facet_counts
10-
django.contrib.admin.EmptyFieldListFilter.get_lookup_condition
11-
django.contrib.admin.RelatedFieldListFilter.get_facet_counts
12-
django.contrib.admin.ShowFacets
13-
django.contrib.admin.SimpleListFilter.get_facet_counts
14-
django.contrib.admin.exceptions.AlreadyRegistered
15-
django.contrib.admin.exceptions.NotRegistered
16-
django.contrib.admin.filters.AllValuesFieldListFilter.get_facet_counts
17-
django.contrib.admin.filters.BooleanFieldListFilter.get_facet_counts
18-
django.contrib.admin.filters.ChoicesFieldListFilter.get_facet_counts
19-
django.contrib.admin.filters.DateFieldListFilter.get_facet_counts
20-
django.contrib.admin.filters.EmptyFieldListFilter.get_facet_counts
21-
django.contrib.admin.filters.EmptyFieldListFilter.get_lookup_condition
22-
django.contrib.admin.filters.FacetsMixin
23-
django.contrib.admin.filters.RelatedFieldListFilter.get_facet_counts
24-
django.contrib.admin.filters.SimpleListFilter.get_facet_counts
25-
django.contrib.admin.options.IS_FACETS_VAR
26-
django.contrib.admin.utils.build_q_object_from_lookup_parameters
27-
django.contrib.admin.utils.get_last_value_from_parameters
28-
django.contrib.admin.views.main.ChangeList.get_queryset
295
django.contrib.contenttypes.fields.GenericForeignKey.get_content_type
306
django.contrib.contenttypes.fields.GenericForeignKey.get_prefetch_querysets
317
django.contrib.contenttypes.prefetch

0 commit comments

Comments
 (0)