Skip to content

Commit 3be2d2a

Browse files
Move method defined on BaseManager to Manager to follow runtime behavior (#2637)
* QuerySet method are proxied to `Manager`, not `BaseManager` ``` In [18]: Manager.ordered --------------------------------------------------------------------------- AttributeError Traceback (most recent call last) Cell In[18], line 1 ----> 1 Manager.ordered AttributeError: type object 'Manager' has no attribute 'ordered' ``` https://github.com/django/django/blob/fbdbccf27a7d969a92e6ab8d2b7754e21e69b050/django/db/models/query.py#L1803
1 parent b1b0502 commit 3be2d2a

File tree

6 files changed

+72
-136
lines changed

6 files changed

+72
-136
lines changed

django-stubs/db/models/manager.pyi

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ class BaseManager(Generic[_T]):
3232
@property
3333
def db(self) -> str: ...
3434
def get_queryset(self) -> QuerySet[_T]: ...
35+
def all(self) -> QuerySet[_T]: ...
36+
37+
class Manager(BaseManager[_T]):
3538
# NOTE: The following methods are in common with QuerySet, but note that the use of QuerySet as a return type
3639
# rather than a self-type (_QS), since Manager's QuerySet-like methods return QuerySets and not Managers.
3740
def iterator(self, chunk_size: int | None = ...) -> Iterator[_T]: ...
@@ -92,8 +95,8 @@ class BaseManager(Generic[_T]):
9295
async def aexists(self) -> bool: ...
9396
def explain(self, *, format: Any | None = ..., **options: Any) -> str: ...
9497
async def aexplain(self, *, format: Any | None = ..., **options: Any) -> str: ...
95-
def contains(self, objs: Model) -> bool: ...
96-
async def acontains(self, objs: Model) -> bool: ...
98+
def contains(self, obj: Model) -> bool: ...
99+
async def acontains(self, obj: Model) -> bool: ...
97100
def raw(
98101
self,
99102
raw_query: str,
@@ -110,7 +113,6 @@ class BaseManager(Generic[_T]):
110113
self, field_name: str, kind: str, order: str = ..., tzinfo: datetime.tzinfo | None = ...
111114
) -> QuerySet[_T, datetime.datetime]: ...
112115
def none(self) -> QuerySet[_T]: ...
113-
def all(self) -> QuerySet[_T]: ...
114116
def filter(self, *args: Any, **kwargs: Any) -> QuerySet[_T]: ...
115117
def exclude(self, *args: Any, **kwargs: Any) -> QuerySet[_T]: ...
116118
def complex_filter(self, filter_obj: Any) -> QuerySet[_T]: ...
@@ -142,10 +144,6 @@ class BaseManager(Generic[_T]):
142144
def defer(self, *fields: Any) -> QuerySet[_T]: ...
143145
def only(self, *fields: Any) -> QuerySet[_T]: ...
144146
def using(self, alias: str | None) -> QuerySet[_T]: ...
145-
@property
146-
def ordered(self) -> bool: ...
147-
148-
class Manager(BaseManager[_T]): ...
149147

150148
class ManagerDescriptor:
151149
manager: BaseManager

mypy_django_plugin/main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ def get_additional_deps(self, file: MypyFile) -> list[tuple[int, str, int]]:
136136
return list(deps) + [
137137
# for QuerySet.annotate
138138
self._new_dependency("django_stubs_ext"),
139-
# For BaseManager.from_queryset
139+
# For Manager.from_queryset
140140
self._new_dependency("django.db.models.query"),
141141
]
142142

scripts/stubtest/allowlist_todo.txt

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -927,67 +927,6 @@ django.db.models.lookups.Lookup.allowed_default
927927
django.db.models.lookups.Lookup.lookup_name
928928
django.db.models.lookups.Lookup.output_field
929929
django.db.models.lookups.PatternLookup.process_rhs
930-
django.db.models.manager.BaseManager.aaggregate
931-
django.db.models.manager.BaseManager.abulk_create
932-
django.db.models.manager.BaseManager.abulk_update
933-
django.db.models.manager.BaseManager.acontains
934-
django.db.models.manager.BaseManager.acount
935-
django.db.models.manager.BaseManager.acreate
936-
django.db.models.manager.BaseManager.aearliest
937-
django.db.models.manager.BaseManager.aexists
938-
django.db.models.manager.BaseManager.aexplain
939-
django.db.models.manager.BaseManager.afirst
940-
django.db.models.manager.BaseManager.aget
941-
django.db.models.manager.BaseManager.aget_or_create
942-
django.db.models.manager.BaseManager.aggregate
943-
django.db.models.manager.BaseManager.ain_bulk
944-
django.db.models.manager.BaseManager.aiterator
945-
django.db.models.manager.BaseManager.alast
946-
django.db.models.manager.BaseManager.alatest
947-
django.db.models.manager.BaseManager.alias
948-
django.db.models.manager.BaseManager.annotate
949-
django.db.models.manager.BaseManager.aupdate
950-
django.db.models.manager.BaseManager.aupdate_or_create
951-
django.db.models.manager.BaseManager.bulk_create
952-
django.db.models.manager.BaseManager.bulk_update
953-
django.db.models.manager.BaseManager.complex_filter
954-
django.db.models.manager.BaseManager.contains
955-
django.db.models.manager.BaseManager.count
956-
django.db.models.manager.BaseManager.create
957-
django.db.models.manager.BaseManager.dates
958-
django.db.models.manager.BaseManager.datetimes
959-
django.db.models.manager.BaseManager.defer
960-
django.db.models.manager.BaseManager.difference
961-
django.db.models.manager.BaseManager.distinct
962-
django.db.models.manager.BaseManager.earliest
963-
django.db.models.manager.BaseManager.exclude
964-
django.db.models.manager.BaseManager.exists
965-
django.db.models.manager.BaseManager.explain
966-
django.db.models.manager.BaseManager.extra
967-
django.db.models.manager.BaseManager.filter
968-
django.db.models.manager.BaseManager.first
969-
django.db.models.manager.BaseManager.get
970-
django.db.models.manager.BaseManager.get_or_create
971-
django.db.models.manager.BaseManager.in_bulk
972-
django.db.models.manager.BaseManager.intersection
973-
django.db.models.manager.BaseManager.iterator
974-
django.db.models.manager.BaseManager.last
975-
django.db.models.manager.BaseManager.latest
976-
django.db.models.manager.BaseManager.none
977-
django.db.models.manager.BaseManager.only
978-
django.db.models.manager.BaseManager.order_by
979-
django.db.models.manager.BaseManager.ordered
980-
django.db.models.manager.BaseManager.prefetch_related
981-
django.db.models.manager.BaseManager.raw
982-
django.db.models.manager.BaseManager.reverse
983-
django.db.models.manager.BaseManager.select_for_update
984-
django.db.models.manager.BaseManager.select_related
985-
django.db.models.manager.BaseManager.union
986-
django.db.models.manager.BaseManager.update
987-
django.db.models.manager.BaseManager.update_or_create
988-
django.db.models.manager.BaseManager.using
989-
django.db.models.manager.BaseManager.values
990-
django.db.models.manager.BaseManager.values_list
991930
django.db.models.options.Options.concrete_fields
992931
django.db.models.options.Options.installed
993932
django.db.models.options.Options.local_concrete_fields

tests/typecheck/fields/test_related.yml

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -727,10 +727,10 @@
727727
- path: myapp/models.py
728728
content: |
729729
from django.db import models
730-
from django.db.models.manager import BaseManager
730+
from django.db.models.manager import Manager
731731
class TransactionQuerySet(models.QuerySet):
732732
pass
733-
TransactionManager = BaseManager.from_queryset(TransactionQuerySet)
733+
TransactionManager = Manager.from_queryset(TransactionQuerySet)
734734
class Transaction(models.Model):
735735
pk = 0
736736
objects = TransactionManager()
@@ -752,13 +752,13 @@
752752
- path: myapp/models.py
753753
content: |
754754
from django.db import models
755-
from django.db.models.manager import BaseManager
755+
from django.db.models.manager import Manager
756756
class TransactionQuerySet(models.QuerySet):
757757
def custom(self) -> None:
758758
pass
759759
760-
def TransactionManager() -> BaseManager:
761-
return BaseManager.from_queryset(TransactionQuerySet)()
760+
def TransactionManager() -> Manager:
761+
return Manager.from_queryset(TransactionQuerySet)()
762762
763763
class Transaction(models.Model):
764764
objects = TransactionManager()
@@ -771,10 +771,9 @@
771771
class TransactionLog(models.Model):
772772
transaction = models.ForeignKey(Transaction, on_delete=models.CASCADE)
773773
out: |
774-
myapp/models:11: error: Could not resolve manager type for "myapp.models.Transaction.objects" [django-manager-missing]
775774
myapp/models:13: note: Revealed type is "django.db.models.fields.related_descriptors.RelatedManager[myapp.models.TransactionLog]"
776-
myapp/models:15: note: Revealed type is "myapp.models.UnknownManager[myapp.models.Transaction]"
777-
myapp/models:16: note: Revealed type is "Any"
775+
myapp/models:15: note: Revealed type is "myapp.models.ManagerFromTransactionQuerySet[myapp.models.Transaction]"
776+
myapp/models:16: note: Revealed type is "None"
778777
779778
780779
- case: resolve_primary_keys_for_foreign_keys_with_abstract_self_model
@@ -914,12 +913,12 @@
914913
- path: myapp/models/purchase.py
915914
content: |
916915
from django.db import models
917-
from django.db.models.manager import BaseManager
916+
from django.db.models.manager import Manager
918917
from .querysets import PurchaseQuerySet
919918
from .store import Store
920919
from .user import User
921920
922-
PurchaseManager = BaseManager.from_queryset(PurchaseQuerySet)
921+
PurchaseManager = Manager.from_queryset(PurchaseQuerySet)
923922
class Purchase(models.Model):
924923
objects = PurchaseManager()
925924
store = models.ForeignKey(to=Store, on_delete=models.CASCADE, related_name='purchases')
@@ -937,7 +936,7 @@
937936
- path: myapp/models.py
938937
content: |
939938
from django.db import models
940-
from django.db.models.manager import BaseManager
939+
from django.db.models.manager import Manager
941940
942941
class User(models.Model):
943942
purchases: int
@@ -946,7 +945,7 @@
946945
def queryset_method(self) -> "PurchaseQuerySet":
947946
return self.all()
948947
949-
PurchaseManager = BaseManager.from_queryset(PurchaseQuerySet)
948+
PurchaseManager = Manager.from_queryset(PurchaseQuerySet)
950949
class Purchase(models.Model):
951950
objects = PurchaseManager()
952951
user = models.ForeignKey(to=User, on_delete=models.CASCADE, related_name='purchases')

0 commit comments

Comments
 (0)