plain.models 0.50.0__tar.gz → 0.51.1__tar.gz
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-0.50.0 → plain_models-0.51.1}/PKG-INFO +27 -43
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/CHANGELOG.md +24 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/README.md +26 -42
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/__init__.py +2 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/base/creation.py +2 -2
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/base/introspection.py +8 -4
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/base/schema.py +89 -71
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/base/validation.py +1 -1
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/mysql/compiler.py +1 -1
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/mysql/operations.py +1 -1
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/mysql/schema.py +4 -4
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/postgresql/operations.py +1 -1
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/postgresql/schema.py +3 -3
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/sqlite3/operations.py +1 -1
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/sqlite3/schema.py +61 -50
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/base.py +116 -163
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/cli.py +4 -4
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/constraints.py +14 -9
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/deletion.py +15 -14
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/expressions.py +21 -5
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/fields/__init__.py +20 -16
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/fields/json.py +3 -3
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/fields/related.py +73 -71
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/fields/related_descriptors.py +2 -2
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/fields/related_lookups.py +1 -1
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/fields/related_managers.py +21 -32
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/fields/reverse_related.py +8 -8
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/forms.py +12 -12
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/indexes.py +5 -4
- plain_models-0.50.0/plain/models/options.py → plain_models-0.51.1/plain/models/meta.py +118 -182
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/operations/base.py +1 -1
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/operations/fields.py +6 -6
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/operations/models.py +18 -16
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/recorder.py +9 -5
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/state.py +35 -46
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/utils.py +1 -1
- plain_models-0.51.1/plain/models/options.py +233 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/preflight.py +7 -5
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/query.py +119 -65
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/query_utils.py +18 -13
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/registry.py +6 -5
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/sql/compiler.py +51 -37
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/sql/query.py +77 -68
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/sql/subqueries.py +4 -4
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/utils.py +4 -1
- {plain_models-0.50.0 → plain_models-0.51.1}/pyproject.toml +1 -1
- plain_models-0.51.1/tests/app/examples/migrations/0004_defaultquerysetmodel_mixintestmodel_and_more.py +68 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/tests/app/examples/models.py +24 -6
- {plain_models-0.50.0 → plain_models-0.51.1}/tests/test_manager_assignment.py +12 -25
- plain_models-0.51.1/tests/test_models.py +43 -0
- plain_models-0.50.0/tests/test_models.py +0 -25
- {plain_models-0.50.0 → plain_models-0.51.1}/.gitignore +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/LICENSE +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/README.md +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/AGENTS.md +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/aggregates.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/__init__.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/base/__init__.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/base/base.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/base/client.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/base/features.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/base/operations.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/ddl_references.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/mysql/__init__.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/mysql/base.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/mysql/client.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/mysql/creation.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/mysql/features.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/mysql/introspection.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/mysql/validation.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/postgresql/__init__.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/postgresql/base.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/postgresql/client.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/postgresql/creation.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/postgresql/features.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/postgresql/introspection.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/sqlite3/__init__.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/sqlite3/_functions.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/sqlite3/base.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/sqlite3/client.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/sqlite3/creation.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/sqlite3/features.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/sqlite3/introspection.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backends/utils.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backups/__init__.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backups/cli.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backups/clients.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/backups/core.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/config.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/connections.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/constants.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/database_url.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/db.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/default_settings.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/entrypoints.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/enums.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/exceptions.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/fields/mixins.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/functions/__init__.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/functions/comparison.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/functions/datetime.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/functions/math.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/functions/mixins.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/functions/text.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/functions/window.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/lookups.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/__init__.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/autodetector.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/exceptions.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/executor.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/graph.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/loader.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/migration.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/operations/__init__.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/operations/special.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/optimizer.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/questioner.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/serializer.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/migrations/writer.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/otel.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/sql/__init__.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/sql/constants.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/sql/datastructures.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/sql/where.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/test/__init__.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/test/pytest.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/test/utils.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/plain/models/transaction.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/tests/app/examples/migrations/0001_initial.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/tests/app/examples/migrations/0002_test_field_removed.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/tests/app/examples/migrations/0003_deleteparent_childsetnull_childsetdefault_and_more.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/tests/app/examples/migrations/__init__.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/tests/app/settings.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/tests/app/urls.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/tests/test_database_url.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/tests/test_delete_behaviors.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/tests/test_exceptions.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/tests/test_related_descriptors.py +0 -0
- {plain_models-0.50.0 → plain_models-0.51.1}/tests/test_related_manager_api.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: plain.models
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.51.1
|
4
4
|
Summary: Model your data and store it in a database.
|
5
5
|
Author-email: Dave Gaeddert <dave.gaeddert@dropseed.dev>
|
6
6
|
License-File: LICENSE
|
@@ -211,31 +211,32 @@ class User(models.Model):
|
|
211
211
|
username = models.CharField(max_length=150)
|
212
212
|
age = models.IntegerField()
|
213
213
|
|
214
|
-
|
215
|
-
indexes
|
214
|
+
model_options = models.Options(
|
215
|
+
indexes=[
|
216
216
|
models.Index(fields=["email"]),
|
217
217
|
models.Index(fields=["-created_at"], name="user_created_idx"),
|
218
|
-
]
|
219
|
-
constraints
|
218
|
+
],
|
219
|
+
constraints=[
|
220
220
|
models.UniqueConstraint(fields=["email", "username"], name="unique_user"),
|
221
221
|
models.CheckConstraint(check=models.Q(age__gte=0), name="age_positive"),
|
222
|
-
]
|
222
|
+
],
|
223
|
+
)
|
223
224
|
```
|
224
225
|
|
225
226
|
## Custom QuerySets
|
226
227
|
|
227
|
-
With the Manager functionality now merged into QuerySet, you can customize [`QuerySet`](./query.py#QuerySet) classes to provide specialized query methods.
|
228
|
-
|
229
|
-
### Setting a default QuerySet for a model
|
228
|
+
With the Manager functionality now merged into QuerySet, you can customize [`QuerySet`](./query.py#QuerySet) classes to provide specialized query methods.
|
230
229
|
|
231
|
-
|
230
|
+
Define a custom QuerySet and assign it to your model's `query` attribute:
|
232
231
|
|
233
232
|
```python
|
234
|
-
|
235
|
-
|
233
|
+
from typing import Self
|
234
|
+
|
235
|
+
class PublishedQuerySet(models.QuerySet["Article"]):
|
236
|
+
def published_only(self) -> Self:
|
236
237
|
return self.filter(status="published")
|
237
238
|
|
238
|
-
def draft_only(self):
|
239
|
+
def draft_only(self) -> Self:
|
239
240
|
return self.filter(status="draft")
|
240
241
|
|
241
242
|
@models.register_model
|
@@ -243,50 +244,33 @@ class Article(models.Model):
|
|
243
244
|
title = models.CharField(max_length=200)
|
244
245
|
status = models.CharField(max_length=20)
|
245
246
|
|
246
|
-
|
247
|
-
queryset_class = PublishedQuerySet
|
247
|
+
query = PublishedQuerySet()
|
248
248
|
|
249
|
-
# Usage - all methods available on Article.
|
249
|
+
# Usage - all methods available on Article.query
|
250
250
|
all_articles = Article.query.all()
|
251
251
|
published_articles = Article.query.published_only()
|
252
252
|
draft_articles = Article.query.draft_only()
|
253
253
|
```
|
254
254
|
|
255
|
-
|
256
|
-
|
257
|
-
You can also use custom QuerySets manually without setting them as the default:
|
255
|
+
Custom methods can be chained with built-in QuerySet methods:
|
258
256
|
|
259
257
|
```python
|
260
|
-
|
261
|
-
|
262
|
-
return self.filter(special=True)
|
263
|
-
|
264
|
-
# Create and use the QuerySet manually
|
265
|
-
special_qs = SpecialQuerySet(model=Article)
|
266
|
-
special_articles = special_qs.special_filter()
|
258
|
+
# Chaining works naturally
|
259
|
+
recent_published = Article.query.published_only().order_by("-created_at")[:10]
|
267
260
|
```
|
268
261
|
|
269
|
-
###
|
262
|
+
### Programmatic QuerySet usage
|
270
263
|
|
271
|
-
For
|
264
|
+
For internal code that needs to create QuerySet instances programmatically, use `from_model()`:
|
272
265
|
|
273
266
|
```python
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
status = models.CharField(max_length=20)
|
278
|
-
|
279
|
-
@classmethod
|
280
|
-
def published(cls):
|
281
|
-
return PublishedQuerySet(model=cls).published_only()
|
282
|
-
|
283
|
-
@classmethod
|
284
|
-
def drafts(cls):
|
285
|
-
return PublishedQuerySet(model=cls).draft_only()
|
267
|
+
class SpecialQuerySet(models.QuerySet["Article"]):
|
268
|
+
def special_filter(self) -> Self:
|
269
|
+
return self.filter(special=True)
|
286
270
|
|
287
|
-
#
|
288
|
-
|
289
|
-
|
271
|
+
# Create and use the QuerySet programmatically
|
272
|
+
special_qs = SpecialQuerySet.from_model(Article)
|
273
|
+
special_articles = special_qs.special_filter()
|
290
274
|
```
|
291
275
|
|
292
276
|
## Forms
|
@@ -1,5 +1,29 @@
|
|
1
1
|
# plain-models changelog
|
2
2
|
|
3
|
+
## [0.51.1](https://github.com/dropseed/plain/releases/plain-models@0.51.1) (2025-10-08)
|
4
|
+
|
5
|
+
### What's changed
|
6
|
+
|
7
|
+
- Fixed a bug in `Subquery` and `Exists` expressions that was using the old `query` attribute name instead of `sql_query` when extracting the SQL query from a QuerySet ([79ca52d](https://github.com/dropseed/plain/commit/79ca52d32e))
|
8
|
+
|
9
|
+
### Upgrade instructions
|
10
|
+
|
11
|
+
- No changes required
|
12
|
+
|
13
|
+
## [0.51.0](https://github.com/dropseed/plain/releases/plain-models@0.51.0) (2025-10-07)
|
14
|
+
|
15
|
+
### What's changed
|
16
|
+
|
17
|
+
- Model metadata has been split into two separate descriptors: `model_options` for user-defined configuration and `_model_meta` for internal metadata ([73ba469](https://github.com/dropseed/plain/commit/73ba469ba0), [17a378d](https://github.com/dropseed/plain/commit/17a378dcfb))
|
18
|
+
- The `_meta` attribute has been replaced with `model_options` for user-defined options like indexes, constraints, and database settings ([17a378d](https://github.com/dropseed/plain/commit/17a378dcfb))
|
19
|
+
- Custom QuerySets are now assigned directly to the `query` class attribute instead of using `Meta.queryset_class` ([2578301](https://github.com/dropseed/plain/commit/2578301819))
|
20
|
+
- Added comprehensive type improvements to model metadata and related fields for better IDE support ([3b477a0](https://github.com/dropseed/plain/commit/3b477a0d43))
|
21
|
+
|
22
|
+
### Upgrade instructions
|
23
|
+
|
24
|
+
- Replace `Meta.queryset_class = CustomQuerySet` with `query = CustomQuerySet()` as a class attribute on your models
|
25
|
+
- Replace `class Meta:` with `model_options = models.Options(...)` in your models
|
26
|
+
|
3
27
|
## [0.50.0](https://github.com/dropseed/plain/releases/plain-models@0.50.0) (2025-10-06)
|
4
28
|
|
5
29
|
### What's changed
|
@@ -200,31 +200,32 @@ class User(models.Model):
|
|
200
200
|
username = models.CharField(max_length=150)
|
201
201
|
age = models.IntegerField()
|
202
202
|
|
203
|
-
|
204
|
-
indexes
|
203
|
+
model_options = models.Options(
|
204
|
+
indexes=[
|
205
205
|
models.Index(fields=["email"]),
|
206
206
|
models.Index(fields=["-created_at"], name="user_created_idx"),
|
207
|
-
]
|
208
|
-
constraints
|
207
|
+
],
|
208
|
+
constraints=[
|
209
209
|
models.UniqueConstraint(fields=["email", "username"], name="unique_user"),
|
210
210
|
models.CheckConstraint(check=models.Q(age__gte=0), name="age_positive"),
|
211
|
-
]
|
211
|
+
],
|
212
|
+
)
|
212
213
|
```
|
213
214
|
|
214
215
|
## Custom QuerySets
|
215
216
|
|
216
|
-
With the Manager functionality now merged into QuerySet, you can customize [`QuerySet`](./query.py#QuerySet) classes to provide specialized query methods.
|
217
|
-
|
218
|
-
### Setting a default QuerySet for a model
|
217
|
+
With the Manager functionality now merged into QuerySet, you can customize [`QuerySet`](./query.py#QuerySet) classes to provide specialized query methods.
|
219
218
|
|
220
|
-
|
219
|
+
Define a custom QuerySet and assign it to your model's `query` attribute:
|
221
220
|
|
222
221
|
```python
|
223
|
-
|
224
|
-
|
222
|
+
from typing import Self
|
223
|
+
|
224
|
+
class PublishedQuerySet(models.QuerySet["Article"]):
|
225
|
+
def published_only(self) -> Self:
|
225
226
|
return self.filter(status="published")
|
226
227
|
|
227
|
-
def draft_only(self):
|
228
|
+
def draft_only(self) -> Self:
|
228
229
|
return self.filter(status="draft")
|
229
230
|
|
230
231
|
@models.register_model
|
@@ -232,50 +233,33 @@ class Article(models.Model):
|
|
232
233
|
title = models.CharField(max_length=200)
|
233
234
|
status = models.CharField(max_length=20)
|
234
235
|
|
235
|
-
|
236
|
-
queryset_class = PublishedQuerySet
|
236
|
+
query = PublishedQuerySet()
|
237
237
|
|
238
|
-
# Usage - all methods available on Article.
|
238
|
+
# Usage - all methods available on Article.query
|
239
239
|
all_articles = Article.query.all()
|
240
240
|
published_articles = Article.query.published_only()
|
241
241
|
draft_articles = Article.query.draft_only()
|
242
242
|
```
|
243
243
|
|
244
|
-
|
245
|
-
|
246
|
-
You can also use custom QuerySets manually without setting them as the default:
|
244
|
+
Custom methods can be chained with built-in QuerySet methods:
|
247
245
|
|
248
246
|
```python
|
249
|
-
|
250
|
-
|
251
|
-
return self.filter(special=True)
|
252
|
-
|
253
|
-
# Create and use the QuerySet manually
|
254
|
-
special_qs = SpecialQuerySet(model=Article)
|
255
|
-
special_articles = special_qs.special_filter()
|
247
|
+
# Chaining works naturally
|
248
|
+
recent_published = Article.query.published_only().order_by("-created_at")[:10]
|
256
249
|
```
|
257
250
|
|
258
|
-
###
|
251
|
+
### Programmatic QuerySet usage
|
259
252
|
|
260
|
-
For
|
253
|
+
For internal code that needs to create QuerySet instances programmatically, use `from_model()`:
|
261
254
|
|
262
255
|
```python
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
status = models.CharField(max_length=20)
|
267
|
-
|
268
|
-
@classmethod
|
269
|
-
def published(cls):
|
270
|
-
return PublishedQuerySet(model=cls).published_only()
|
271
|
-
|
272
|
-
@classmethod
|
273
|
-
def drafts(cls):
|
274
|
-
return PublishedQuerySet(model=cls).draft_only()
|
256
|
+
class SpecialQuerySet(models.QuerySet["Article"]):
|
257
|
+
def special_filter(self) -> Self:
|
258
|
+
return self.filter(special=True)
|
275
259
|
|
276
|
-
#
|
277
|
-
|
278
|
-
|
260
|
+
# Create and use the QuerySet programmatically
|
261
|
+
special_qs = SpecialQuerySet.from_model(Article)
|
262
|
+
special_articles = special_qs.special_filter()
|
279
263
|
```
|
280
264
|
|
281
265
|
## Forms
|
@@ -63,6 +63,7 @@ from .registry import models_registry, register_model
|
|
63
63
|
|
64
64
|
# Imports that would create circular imports if sorted
|
65
65
|
from .base import DEFERRED, Model # isort:skip
|
66
|
+
from .options import Options # isort:skip
|
66
67
|
from .fields.related import ( # isort:skip
|
67
68
|
ForeignKey,
|
68
69
|
ManyToManyField,
|
@@ -104,6 +105,7 @@ __all__ += [
|
|
104
105
|
"JSONField",
|
105
106
|
"Lookup",
|
106
107
|
"Transform",
|
108
|
+
"Options",
|
107
109
|
"Prefetch",
|
108
110
|
"Q",
|
109
111
|
"QuerySet",
|
@@ -98,7 +98,7 @@ class BaseDatabaseCreation:
|
|
98
98
|
# and package_config.package_label in loader.migrated_packages
|
99
99
|
# ):
|
100
100
|
# for model in package_config.get_models():
|
101
|
-
# if model.
|
101
|
+
# if model.model_options.can_migrate(
|
102
102
|
# self.connection
|
103
103
|
# ) and router.allow_migrate_model(self.connection.alias, model):
|
104
104
|
# queryset = model._base_manager.using(
|
@@ -127,7 +127,7 @@ class BaseDatabaseCreation:
|
|
127
127
|
# "json", data, using=self.connection.alias
|
128
128
|
# ):
|
129
129
|
# obj.save()
|
130
|
-
# table_names.add(obj.object.
|
130
|
+
# table_names.add(obj.object.model_options.db_table)
|
131
131
|
# # Manually check for any invalid keys that might have been added,
|
132
132
|
# # because constraint checks were disabled.
|
133
133
|
# self.connection.check_constraints(table_names=table_names)
|
@@ -94,7 +94,7 @@ class BaseDatabaseIntrospection:
|
|
94
94
|
for model in models_registry.get_models(
|
95
95
|
package_label=package_config.package_label
|
96
96
|
)
|
97
|
-
if model.
|
97
|
+
if model.model_options.can_migrate(self.connection)
|
98
98
|
)
|
99
99
|
|
100
100
|
def plain_table_names(
|
@@ -108,8 +108,10 @@ class BaseDatabaseIntrospection:
|
|
108
108
|
"""
|
109
109
|
tables = set()
|
110
110
|
for model in self.get_migratable_models():
|
111
|
-
tables.add(model.
|
112
|
-
tables.update(
|
111
|
+
tables.add(model.model_options.db_table)
|
112
|
+
tables.update(
|
113
|
+
f.m2m_db_table() for f in model._model_meta.local_many_to_many
|
114
|
+
)
|
113
115
|
tables = list(tables)
|
114
116
|
if only_existing:
|
115
117
|
existing_tables = set(self.table_names(include_views=include_views))
|
@@ -128,7 +130,9 @@ class BaseDatabaseIntrospection:
|
|
128
130
|
for model in self.get_migratable_models():
|
129
131
|
sequence_list.extend(
|
130
132
|
self.get_sequences(
|
131
|
-
cursor,
|
133
|
+
cursor,
|
134
|
+
model.model_options.db_table,
|
135
|
+
model._model_meta.local_fields,
|
132
136
|
)
|
133
137
|
)
|
134
138
|
return sequence_list
|