plain.models 0.41.1__py3-none-any.whl → 0.43.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plain/models/CHANGELOG.md +32 -0
- plain/models/README.md +65 -22
- plain/models/__init__.py +0 -2
- plain/models/base.py +14 -35
- plain/models/cli.py +16 -22
- plain/models/constraints.py +1 -1
- plain/models/deletion.py +1 -1
- plain/models/fields/__init__.py +1 -1
- plain/models/fields/related.py +7 -32
- plain/models/fields/related_descriptors.py +81 -631
- plain/models/fields/related_lookups.py +2 -2
- plain/models/fields/related_managers.py +629 -0
- plain/models/fields/reverse_related.py +5 -8
- plain/models/forms.py +1 -1
- plain/models/migrations/autodetector.py +0 -18
- plain/models/migrations/operations/__init__.py +0 -2
- plain/models/migrations/operations/models.py +3 -57
- plain/models/migrations/operations/special.py +2 -8
- plain/models/migrations/recorder.py +1 -1
- plain/models/migrations/serializer.py +0 -12
- plain/models/migrations/state.py +1 -55
- plain/models/options.py +23 -86
- plain/models/query.py +10 -41
- plain/models/query_utils.py +1 -1
- plain/models/sql/compiler.py +5 -5
- plain/models/sql/query.py +2 -2
- {plain_models-0.41.1.dist-info → plain_models-0.43.0.dist-info}/METADATA +66 -23
- {plain_models-0.41.1.dist-info → plain_models-0.43.0.dist-info}/RECORD +31 -31
- plain/models/manager.py +0 -176
- {plain_models-0.41.1.dist-info → plain_models-0.43.0.dist-info}/WHEEL +0 -0
- {plain_models-0.41.1.dist-info → plain_models-0.43.0.dist-info}/entry_points.txt +0 -0
- {plain_models-0.41.1.dist-info → plain_models-0.43.0.dist-info}/licenses/LICENSE +0 -0
@@ -152,7 +152,6 @@ class MigrationAutodetector:
|
|
152
152
|
self.generate_deleted_models()
|
153
153
|
self.generate_created_models()
|
154
154
|
self.generate_altered_options()
|
155
|
-
self.generate_altered_managers()
|
156
155
|
self.generate_altered_db_table_comment()
|
157
156
|
|
158
157
|
# Create the renamed fields and store them in self.renamed_fields.
|
@@ -600,7 +599,6 @@ class MigrationAutodetector:
|
|
600
599
|
],
|
601
600
|
options=model_state.options,
|
602
601
|
bases=model_state.bases,
|
603
|
-
managers=model_state.managers,
|
604
602
|
),
|
605
603
|
dependencies=dependencies,
|
606
604
|
beginning=True,
|
@@ -1258,22 +1256,6 @@ class MigrationAutodetector:
|
|
1258
1256
|
),
|
1259
1257
|
)
|
1260
1258
|
|
1261
|
-
def generate_altered_managers(self):
|
1262
|
-
for package_label, model_name in sorted(self.kept_model_keys):
|
1263
|
-
old_model_name = self.renamed_models.get(
|
1264
|
-
(package_label, model_name), model_name
|
1265
|
-
)
|
1266
|
-
old_model_state = self.from_state.models[package_label, old_model_name]
|
1267
|
-
new_model_state = self.to_state.models[package_label, model_name]
|
1268
|
-
if old_model_state.managers != new_model_state.managers:
|
1269
|
-
self.add_operation(
|
1270
|
-
package_label,
|
1271
|
-
operations.AlterModelManagers(
|
1272
|
-
name=model_name,
|
1273
|
-
managers=new_model_state.managers,
|
1274
|
-
),
|
1275
|
-
)
|
1276
|
-
|
1277
1259
|
def arrange_for_graph(self, changes, graph, migration_name=None):
|
1278
1260
|
"""
|
1279
1261
|
Take a result from changes() and a MigrationGraph, and fix the names
|
@@ -2,7 +2,6 @@ from .fields import AddField, AlterField, RemoveField, RenameField
|
|
2
2
|
from .models import (
|
3
3
|
AddConstraint,
|
4
4
|
AddIndex,
|
5
|
-
AlterModelManagers,
|
6
5
|
AlterModelOptions,
|
7
6
|
AlterModelTable,
|
8
7
|
AlterModelTableComment,
|
@@ -34,5 +33,4 @@ __all__ = [
|
|
34
33
|
"SeparateDatabaseAndState",
|
35
34
|
"RunSQL",
|
36
35
|
"RunPython",
|
37
|
-
"AlterModelManagers",
|
38
36
|
]
|
@@ -41,16 +41,14 @@ class ModelOperation(Operation):
|
|
41
41
|
class CreateModel(ModelOperation):
|
42
42
|
"""Create a model's table."""
|
43
43
|
|
44
|
-
serialization_expand_args = ["fields", "options"
|
44
|
+
serialization_expand_args = ["fields", "options"]
|
45
45
|
|
46
|
-
def __init__(self, name, fields, options=None, bases=None
|
46
|
+
def __init__(self, name, fields, options=None, bases=None):
|
47
47
|
self.fields = fields
|
48
48
|
self.options = options or {}
|
49
49
|
self.bases = bases or (models.Model,)
|
50
|
-
self.managers = managers or []
|
51
50
|
super().__init__(name)
|
52
|
-
# Sanity-check that there are no duplicated field names
|
53
|
-
# manager names
|
51
|
+
# Sanity-check that there are no duplicated field names or bases
|
54
52
|
_check_for_duplicates("fields", (name for name, _ in self.fields))
|
55
53
|
_check_for_duplicates(
|
56
54
|
"bases",
|
@@ -63,7 +61,6 @@ class CreateModel(ModelOperation):
|
|
63
61
|
for base in self.bases
|
64
62
|
),
|
65
63
|
)
|
66
|
-
_check_for_duplicates("managers", (name for name, _ in self.managers))
|
67
64
|
|
68
65
|
def deconstruct(self):
|
69
66
|
kwargs = {
|
@@ -74,8 +71,6 @@ class CreateModel(ModelOperation):
|
|
74
71
|
kwargs["options"] = self.options
|
75
72
|
if self.bases and self.bases != (models.Model,):
|
76
73
|
kwargs["bases"] = self.bases
|
77
|
-
if self.managers and self.managers != [("objects", models.Manager())]:
|
78
|
-
kwargs["managers"] = self.managers
|
79
74
|
return (self.__class__.__qualname__, [], kwargs)
|
80
75
|
|
81
76
|
def state_forwards(self, package_label, state):
|
@@ -86,7 +81,6 @@ class CreateModel(ModelOperation):
|
|
86
81
|
list(self.fields),
|
87
82
|
dict(self.options),
|
88
83
|
tuple(self.bases),
|
89
|
-
list(self.managers),
|
90
84
|
)
|
91
85
|
)
|
92
86
|
|
@@ -141,7 +135,6 @@ class CreateModel(ModelOperation):
|
|
141
135
|
fields=self.fields,
|
142
136
|
options=self.options,
|
143
137
|
bases=self.bases,
|
144
|
-
managers=self.managers,
|
145
138
|
),
|
146
139
|
]
|
147
140
|
elif (
|
@@ -158,20 +151,6 @@ class CreateModel(ModelOperation):
|
|
158
151
|
fields=self.fields,
|
159
152
|
options=options,
|
160
153
|
bases=self.bases,
|
161
|
-
managers=self.managers,
|
162
|
-
),
|
163
|
-
]
|
164
|
-
elif (
|
165
|
-
isinstance(operation, AlterModelManagers)
|
166
|
-
and self.name_lower == operation.name_lower
|
167
|
-
):
|
168
|
-
return [
|
169
|
-
CreateModel(
|
170
|
-
self.name,
|
171
|
-
fields=self.fields,
|
172
|
-
options=self.options,
|
173
|
-
bases=self.bases,
|
174
|
-
managers=operation.managers,
|
175
154
|
),
|
176
155
|
]
|
177
156
|
elif (
|
@@ -185,7 +164,6 @@ class CreateModel(ModelOperation):
|
|
185
164
|
fields=self.fields + [(operation.name, operation.field)],
|
186
165
|
options=self.options,
|
187
166
|
bases=self.bases,
|
188
|
-
managers=self.managers,
|
189
167
|
),
|
190
168
|
]
|
191
169
|
elif isinstance(operation, AlterField):
|
@@ -198,7 +176,6 @@ class CreateModel(ModelOperation):
|
|
198
176
|
],
|
199
177
|
options=self.options,
|
200
178
|
bases=self.bases,
|
201
|
-
managers=self.managers,
|
202
179
|
),
|
203
180
|
]
|
204
181
|
elif isinstance(operation, RemoveField):
|
@@ -214,7 +191,6 @@ class CreateModel(ModelOperation):
|
|
214
191
|
],
|
215
192
|
options=options,
|
216
193
|
bases=self.bases,
|
217
|
-
managers=self.managers,
|
218
194
|
),
|
219
195
|
]
|
220
196
|
elif isinstance(operation, RenameField):
|
@@ -229,7 +205,6 @@ class CreateModel(ModelOperation):
|
|
229
205
|
],
|
230
206
|
options=options,
|
231
207
|
bases=self.bases,
|
232
|
-
managers=self.managers,
|
233
208
|
),
|
234
209
|
]
|
235
210
|
return super().reduce(operation, package_label)
|
@@ -447,9 +422,6 @@ class AlterModelOptions(ModelOptionOperation):
|
|
447
422
|
|
448
423
|
# Model options we want to compare and preserve in an AlterModelOptions op
|
449
424
|
ALTER_OPTION_KEYS = [
|
450
|
-
"base_manager_name",
|
451
|
-
"default_manager_name",
|
452
|
-
"default_related_name",
|
453
425
|
"ordering",
|
454
426
|
]
|
455
427
|
|
@@ -483,32 +455,6 @@ class AlterModelOptions(ModelOptionOperation):
|
|
483
455
|
return f"alter_{self.name_lower}_options"
|
484
456
|
|
485
457
|
|
486
|
-
class AlterModelManagers(ModelOptionOperation):
|
487
|
-
"""Alter the model's managers."""
|
488
|
-
|
489
|
-
serialization_expand_args = ["managers"]
|
490
|
-
|
491
|
-
def __init__(self, name, managers):
|
492
|
-
self.managers = managers
|
493
|
-
super().__init__(name)
|
494
|
-
|
495
|
-
def deconstruct(self):
|
496
|
-
return (self.__class__.__qualname__, [self.name, self.managers], {})
|
497
|
-
|
498
|
-
def state_forwards(self, package_label, state):
|
499
|
-
state.alter_model_managers(package_label, self.name_lower, self.managers)
|
500
|
-
|
501
|
-
def database_forwards(self, package_label, schema_editor, from_state, to_state):
|
502
|
-
pass
|
503
|
-
|
504
|
-
def describe(self):
|
505
|
-
return f"Change managers on {self.name}"
|
506
|
-
|
507
|
-
@property
|
508
|
-
def migration_name_fragment(self):
|
509
|
-
return f"alter_{self.name_lower}_managers"
|
510
|
-
|
511
|
-
|
512
458
|
class IndexOperation(Operation):
|
513
459
|
option_name = "indexes"
|
514
460
|
|
@@ -49,10 +49,9 @@ class RunSQL(Operation):
|
|
49
49
|
by this SQL change, in case it's custom column/table creation/deletion.
|
50
50
|
"""
|
51
51
|
|
52
|
-
def __init__(self, sql, *, state_operations=None,
|
52
|
+
def __init__(self, sql, *, state_operations=None, elidable=False):
|
53
53
|
self.sql = sql
|
54
54
|
self.state_operations = state_operations or []
|
55
|
-
self.hints = hints or {}
|
56
55
|
self.elidable = elidable
|
57
56
|
|
58
57
|
def deconstruct(self):
|
@@ -61,8 +60,6 @@ class RunSQL(Operation):
|
|
61
60
|
}
|
62
61
|
if self.state_operations:
|
63
62
|
kwargs["state_operations"] = self.state_operations
|
64
|
-
if self.hints:
|
65
|
-
kwargs["hints"] = self.hints
|
66
63
|
return (self.__class__.__qualname__, [], kwargs)
|
67
64
|
|
68
65
|
def state_forwards(self, package_label, state):
|
@@ -99,13 +96,12 @@ class RunPython(Operation):
|
|
99
96
|
|
100
97
|
reduces_to_sql = False
|
101
98
|
|
102
|
-
def __init__(self, code, *, atomic=None,
|
99
|
+
def __init__(self, code, *, atomic=None, elidable=False):
|
103
100
|
self.atomic = atomic
|
104
101
|
# Forwards code
|
105
102
|
if not callable(code):
|
106
103
|
raise ValueError("RunPython must be supplied with a callable")
|
107
104
|
self.code = code
|
108
|
-
self.hints = hints or {}
|
109
105
|
self.elidable = elidable
|
110
106
|
|
111
107
|
def deconstruct(self):
|
@@ -114,8 +110,6 @@ class RunPython(Operation):
|
|
114
110
|
}
|
115
111
|
if self.atomic is not None:
|
116
112
|
kwargs["atomic"] = self.atomic
|
117
|
-
if self.hints:
|
118
|
-
kwargs["hints"] = self.hints
|
119
113
|
return (self.__class__.__qualname__, [], kwargs)
|
120
114
|
|
121
115
|
def state_forwards(self, package_label, state):
|
@@ -215,16 +215,6 @@ class ModelFieldSerializer(DeconstructableSerializer):
|
|
215
215
|
return self.serialize_deconstructed(path, args, kwargs)
|
216
216
|
|
217
217
|
|
218
|
-
class ModelManagerSerializer(DeconstructableSerializer):
|
219
|
-
def serialize(self):
|
220
|
-
as_manager, manager_path, qs_path, args, kwargs = self.value.deconstruct()
|
221
|
-
if as_manager:
|
222
|
-
name, imports = self._serialize_path(qs_path)
|
223
|
-
return f"{name}.as_manager()", imports
|
224
|
-
else:
|
225
|
-
return self.serialize_deconstructed(manager_path, args, kwargs)
|
226
|
-
|
227
|
-
|
228
218
|
class OperationSerializer(BaseSerializer):
|
229
219
|
def serialize(self):
|
230
220
|
from plain.models.migrations.writer import OperationWriter
|
@@ -359,8 +349,6 @@ def serializer_factory(value):
|
|
359
349
|
|
360
350
|
if isinstance(value, models.Field):
|
361
351
|
return ModelFieldSerializer(value)
|
362
|
-
if isinstance(value, models.manager.BaseManager):
|
363
|
-
return ModelManagerSerializer(value)
|
364
352
|
if isinstance(value, Operation):
|
365
353
|
return OperationSerializer(value)
|
366
354
|
if isinstance(value, type):
|
plain/models/migrations/state.py
CHANGED
@@ -12,7 +12,6 @@ from plain.models.options import DEFAULT_NAMES
|
|
12
12
|
from plain.models.registry import ModelsRegistry
|
13
13
|
from plain.models.registry import models_registry as global_models
|
14
14
|
from plain.packages import packages_registry
|
15
|
-
from plain.utils.module_loading import import_string
|
16
15
|
|
17
16
|
from .exceptions import InvalidBasesError
|
18
17
|
from .utils import resolve_relation
|
@@ -176,11 +175,6 @@ class ProjectState:
|
|
176
175
|
model_state.options.pop(key, False)
|
177
176
|
self.reload_model(package_label, model_name, delay=True)
|
178
177
|
|
179
|
-
def alter_model_managers(self, package_label, model_name, managers):
|
180
|
-
model_state = self.models[package_label, model_name]
|
181
|
-
model_state.managers = list(managers)
|
182
|
-
self.reload_model(package_label, model_name, delay=True)
|
183
|
-
|
184
178
|
def _append_option(self, package_label, model_name, option_name, obj):
|
185
179
|
model_state = self.models[package_label, model_name]
|
186
180
|
model_state.options[option_name] = [*model_state.options[option_name], obj]
|
@@ -598,9 +592,7 @@ class ModelState:
|
|
598
592
|
assign new ones, as these are not detached during a clone.
|
599
593
|
"""
|
600
594
|
|
601
|
-
def __init__(
|
602
|
-
self, package_label, name, fields, options=None, bases=None, managers=None
|
603
|
-
):
|
595
|
+
def __init__(self, package_label, name, fields, options=None, bases=None):
|
604
596
|
self.package_label = package_label
|
605
597
|
self.name = name
|
606
598
|
self.fields = dict(fields)
|
@@ -608,7 +600,6 @@ class ModelState:
|
|
608
600
|
self.options.setdefault("indexes", [])
|
609
601
|
self.options.setdefault("constraints", [])
|
610
602
|
self.bases = bases or (models.Model,)
|
611
|
-
self.managers = managers or []
|
612
603
|
for name, field in self.fields.items():
|
613
604
|
# Sanity-check that fields are NOT already bound to a model.
|
614
605
|
if hasattr(field, "model"):
|
@@ -711,33 +702,6 @@ class ModelState:
|
|
711
702
|
):
|
712
703
|
bases = (models.Model,)
|
713
704
|
|
714
|
-
managers = []
|
715
|
-
manager_names = set()
|
716
|
-
default_manager_shim = None
|
717
|
-
for manager in model._meta.managers:
|
718
|
-
if manager.name in manager_names:
|
719
|
-
# Skip overridden managers.
|
720
|
-
continue
|
721
|
-
elif manager.use_in_migrations:
|
722
|
-
# Copy managers usable in migrations.
|
723
|
-
new_manager = copy.copy(manager)
|
724
|
-
new_manager._set_creation_counter()
|
725
|
-
elif manager is model._base_manager or manager is model._default_manager:
|
726
|
-
# Shim custom managers used as default and base managers.
|
727
|
-
new_manager = models.Manager()
|
728
|
-
new_manager.model = manager.model
|
729
|
-
new_manager.name = manager.name
|
730
|
-
if manager is model._default_manager:
|
731
|
-
default_manager_shim = new_manager
|
732
|
-
else:
|
733
|
-
continue
|
734
|
-
manager_names.add(manager.name)
|
735
|
-
managers.append((manager.name, new_manager))
|
736
|
-
|
737
|
-
# Ignore a shimmed default manager called objects if it's the only one.
|
738
|
-
if managers == [("objects", default_manager_shim)]:
|
739
|
-
managers = []
|
740
|
-
|
741
705
|
# Construct the new ModelState
|
742
706
|
return cls(
|
743
707
|
model._meta.package_label,
|
@@ -745,22 +709,8 @@ class ModelState:
|
|
745
709
|
fields,
|
746
710
|
options,
|
747
711
|
bases,
|
748
|
-
managers,
|
749
712
|
)
|
750
713
|
|
751
|
-
def construct_managers(self):
|
752
|
-
"""Deep-clone the managers using deconstruction."""
|
753
|
-
# Sort all managers by their creation counter
|
754
|
-
sorted_managers = sorted(self.managers, key=lambda v: v[1].creation_counter)
|
755
|
-
for mgr_name, manager in sorted_managers:
|
756
|
-
as_manager, manager_path, qs_path, args, kwargs = manager.deconstruct()
|
757
|
-
if as_manager:
|
758
|
-
qs_class = import_string(qs_path)
|
759
|
-
yield mgr_name, qs_class.as_manager()
|
760
|
-
else:
|
761
|
-
manager_class = import_string(manager_path)
|
762
|
-
yield mgr_name, manager_class(*args, **kwargs)
|
763
|
-
|
764
714
|
def clone(self):
|
765
715
|
"""Return an exact copy of this ModelState."""
|
766
716
|
return self.__class__(
|
@@ -772,7 +722,6 @@ class ModelState:
|
|
772
722
|
# than mutating it.
|
773
723
|
options=dict(self.options),
|
774
724
|
bases=self.bases,
|
775
|
-
managers=list(self.managers),
|
776
725
|
)
|
777
726
|
|
778
727
|
def render(self, models_registry):
|
@@ -799,8 +748,6 @@ class ModelState:
|
|
799
748
|
body["Meta"] = meta
|
800
749
|
body["__module__"] = "__fake__"
|
801
750
|
|
802
|
-
# Restore managers
|
803
|
-
body.update(self.construct_managers())
|
804
751
|
# Then, make a Model object (models_registry.register_model is called in __new__)
|
805
752
|
model_class = type(self.name, bases, body)
|
806
753
|
from plain.models import register_model
|
@@ -840,5 +787,4 @@ class ModelState:
|
|
840
787
|
)
|
841
788
|
and (self.options == other.options)
|
842
789
|
and (self.bases == other.bases)
|
843
|
-
and (self.managers == other.managers)
|
844
790
|
)
|
plain/models/options.py
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
import bisect
|
2
|
-
import copy
|
3
2
|
import inspect
|
4
3
|
from collections import defaultdict
|
5
4
|
from functools import cached_property
|
@@ -9,7 +8,7 @@ from plain.models import models_registry
|
|
9
8
|
from plain.models.constraints import UniqueConstraint
|
10
9
|
from plain.models.db import db_connection
|
11
10
|
from plain.models.fields import PrimaryKeyField
|
12
|
-
from plain.models.
|
11
|
+
from plain.models.query import QuerySet
|
13
12
|
from plain.utils.datastructures import ImmutableList
|
14
13
|
|
15
14
|
PROXY_PARENTS = object()
|
@@ -24,14 +23,12 @@ IMMUTABLE_WARNING = (
|
|
24
23
|
DEFAULT_NAMES = (
|
25
24
|
"db_table",
|
26
25
|
"db_table_comment",
|
26
|
+
"queryset_class",
|
27
27
|
"ordering",
|
28
28
|
"package_label",
|
29
29
|
"models_registry",
|
30
|
-
"default_related_name",
|
31
30
|
"required_db_features",
|
32
31
|
"required_db_vendor",
|
33
|
-
"base_manager_name",
|
34
|
-
"default_manager_name",
|
35
32
|
"indexes",
|
36
33
|
"constraints",
|
37
34
|
)
|
@@ -49,10 +46,8 @@ class Options:
|
|
49
46
|
"local_concrete_fields",
|
50
47
|
"_non_pk_concrete_field_names",
|
51
48
|
"_forward_fields_map",
|
52
|
-
"
|
53
|
-
"
|
54
|
-
"base_manager",
|
55
|
-
"default_manager",
|
49
|
+
"base_queryset",
|
50
|
+
"queryset",
|
56
51
|
}
|
57
52
|
REVERSE_PROPERTIES = {"related_objects", "fields_map", "_relation_tree"}
|
58
53
|
|
@@ -62,9 +57,7 @@ class Options:
|
|
62
57
|
self._get_fields_cache = {}
|
63
58
|
self.local_fields = []
|
64
59
|
self.local_many_to_many = []
|
65
|
-
self.
|
66
|
-
self.base_manager_name = None
|
67
|
-
self.default_manager_name = None
|
60
|
+
self.queryset_class = None
|
68
61
|
self.model_name = None
|
69
62
|
self.db_table = ""
|
70
63
|
self.db_table_comment = ""
|
@@ -89,8 +82,6 @@ class Options:
|
|
89
82
|
# A custom app registry to use, if you're making a separate model set.
|
90
83
|
self.models_registry = self.default_models_registry
|
91
84
|
|
92
|
-
self.default_related_name = None
|
93
|
-
|
94
85
|
@property
|
95
86
|
def label(self):
|
96
87
|
return f"{self.package_label}.{self.object_name}"
|
@@ -169,10 +160,6 @@ class Options:
|
|
169
160
|
if not any(f.name == "id" for f in self.local_fields):
|
170
161
|
model.add_to_class("id", PrimaryKeyField())
|
171
162
|
|
172
|
-
def add_manager(self, manager):
|
173
|
-
self.local_managers.append(manager)
|
174
|
-
self._expire_cache()
|
175
|
-
|
176
163
|
def add_field(self, field, private=False):
|
177
164
|
# Insert the given field in the order in which it was created, using
|
178
165
|
# the "creation_counter" attribute of the field.
|
@@ -224,75 +211,25 @@ class Options:
|
|
224
211
|
)
|
225
212
|
return True
|
226
213
|
|
227
|
-
@
|
228
|
-
def
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
managers.append((depth, manager.creation_counter, manager))
|
241
|
-
|
242
|
-
return make_immutable_fields_list(
|
243
|
-
"managers",
|
244
|
-
(m[2] for m in sorted(managers)),
|
245
|
-
)
|
246
|
-
|
247
|
-
@cached_property
|
248
|
-
def managers_map(self):
|
249
|
-
return {manager.name: manager for manager in self.managers}
|
250
|
-
|
251
|
-
@cached_property
|
252
|
-
def base_manager(self):
|
253
|
-
base_manager_name = self.base_manager_name
|
254
|
-
if not base_manager_name:
|
255
|
-
# Get the first parent's base_manager_name if there's one.
|
256
|
-
for parent in self.model.mro()[1:]:
|
257
|
-
if hasattr(parent, "_meta"):
|
258
|
-
if parent._base_manager.name != "_base_manager":
|
259
|
-
base_manager_name = parent._base_manager.name
|
260
|
-
break
|
261
|
-
|
262
|
-
if base_manager_name:
|
263
|
-
try:
|
264
|
-
return self.managers_map[base_manager_name]
|
265
|
-
except KeyError:
|
266
|
-
raise ValueError(
|
267
|
-
f"{self.object_name} has no manager named {base_manager_name!r}"
|
268
|
-
)
|
269
|
-
|
270
|
-
manager = Manager()
|
271
|
-
manager.name = "_base_manager"
|
272
|
-
manager.model = self.model
|
273
|
-
manager.auto_created = True
|
274
|
-
return manager
|
275
|
-
|
276
|
-
@cached_property
|
277
|
-
def default_manager(self):
|
278
|
-
default_manager_name = self.default_manager_name
|
279
|
-
if not default_manager_name and not self.local_managers:
|
280
|
-
# Get the first parent's default_manager_name if there's one.
|
281
|
-
for parent in self.model.mro()[1:]:
|
282
|
-
if hasattr(parent, "_meta"):
|
283
|
-
default_manager_name = parent._meta.default_manager_name
|
284
|
-
break
|
285
|
-
|
286
|
-
if default_manager_name:
|
287
|
-
try:
|
288
|
-
return self.managers_map[default_manager_name]
|
289
|
-
except KeyError:
|
290
|
-
raise ValueError(
|
291
|
-
f"{self.object_name} has no manager named {default_manager_name!r}"
|
292
|
-
)
|
214
|
+
@property
|
215
|
+
def base_queryset(self):
|
216
|
+
"""
|
217
|
+
The base queryset is used by Plain's internal operations like cascading
|
218
|
+
deletes, migrations, and related object lookups. It provides access to
|
219
|
+
all objects in the database without any filtering, ensuring Plain can
|
220
|
+
always see the complete dataset when performing framework operations.
|
221
|
+
|
222
|
+
Unlike user-defined querysets which may filter results (e.g. only active
|
223
|
+
objects), the base queryset must never filter out rows to prevent
|
224
|
+
incomplete results in related queries.
|
225
|
+
"""
|
226
|
+
return QuerySet(model=self.model)
|
293
227
|
|
294
|
-
|
295
|
-
|
228
|
+
@property
|
229
|
+
def queryset(self):
|
230
|
+
if self.queryset_class:
|
231
|
+
return self.queryset_class(model=self.model)
|
232
|
+
return QuerySet(model=self.model)
|
296
233
|
|
297
234
|
@cached_property
|
298
235
|
def fields(self):
|