|
9 | 9 | - [Fields](#fields)
|
10 | 10 | - [Validation](#validation)
|
11 | 11 | - [Indexes and constraints](#indexes-and-constraints)
|
12 |
| -- [Managers](#managers) |
| 12 | +- [Custom QuerySets](#custom-querysets) |
13 | 13 | - [Forms](#forms)
|
14 | 14 | - [Sharing fields across models](#sharing-fields-across-models)
|
15 | 15 | - [Installation](#installation)
|
@@ -85,7 +85,7 @@ Multiple backends are supported, including Postgres, MySQL, and SQLite.
|
85 | 85 |
|
86 | 86 | ## Querying
|
87 | 87 |
|
88 |
| -Models come with a powerful query API through their [`Manager`](./manager.py#Manager) interface: |
| 88 | +Models come with a powerful query API through their [`QuerySet`](./query.py#QuerySet) interface: |
89 | 89 |
|
90 | 90 | ```python
|
91 | 91 | # Get all users
|
@@ -211,28 +211,71 @@ class User(models.Model):
|
211 | 211 | ]
|
212 | 212 | ```
|
213 | 213 |
|
214 |
| -## Managers |
| 214 | +## Custom QuerySets |
215 | 215 |
|
216 |
| -[`Manager`](./manager.py#Manager) objects provide the interface for querying models: |
| 216 | +With the Manager functionality now merged into QuerySet, you can customize [`QuerySet`](./query.py#QuerySet) classes to provide specialized query methods. There are several ways to use custom QuerySets: |
| 217 | + |
| 218 | +### Setting a default QuerySet for a model |
| 219 | + |
| 220 | +Use `Meta.queryset_class` to set a custom QuerySet that will be used by `Model.objects`: |
| 221 | + |
| 222 | +```python |
| 223 | +class PublishedQuerySet(models.QuerySet): |
| 224 | + def published_only(self): |
| 225 | + return self.filter(status="published") |
| 226 | + |
| 227 | + def draft_only(self): |
| 228 | + return self.filter(status="draft") |
| 229 | + |
| 230 | +@models.register_model |
| 231 | +class Article(models.Model): |
| 232 | + title = models.CharField(max_length=200) |
| 233 | + status = models.CharField(max_length=20) |
| 234 | + |
| 235 | + class Meta: |
| 236 | + queryset_class = PublishedQuerySet |
| 237 | + |
| 238 | +# Usage - all methods available on Article.objects |
| 239 | +all_articles = Article.objects.all() |
| 240 | +published_articles = Article.objects.published_only() |
| 241 | +draft_articles = Article.objects.draft_only() |
| 242 | +``` |
| 243 | + |
| 244 | +### Using custom QuerySets without formal attachment |
| 245 | + |
| 246 | +You can also use custom QuerySets manually without setting them as the default: |
217 | 247 |
|
218 | 248 | ```python
|
219 |
| -class PublishedManager(models.Manager): |
220 |
| - def get_queryset(self): |
221 |
| - return super().get_queryset().filter(status="published") |
| 249 | +class SpecialQuerySet(models.QuerySet): |
| 250 | + def special_filter(self): |
| 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() |
| 256 | +``` |
| 257 | + |
| 258 | +### Using classmethods for convenience |
| 259 | + |
| 260 | +For even cleaner API, add classmethods to your model: |
222 | 261 |
|
| 262 | +```python |
| 263 | +@models.register_model |
223 | 264 | class Article(models.Model):
|
224 | 265 | title = models.CharField(max_length=200)
|
225 | 266 | status = models.CharField(max_length=20)
|
226 | 267 |
|
227 |
| - # Default manager |
228 |
| - objects = models.Manager() |
| 268 | + @classmethod |
| 269 | + def published(cls): |
| 270 | + return PublishedQuerySet(model=cls).published_only() |
229 | 271 |
|
230 |
| - # Custom manager |
231 |
| - published = PublishedManager() |
| 272 | + @classmethod |
| 273 | + def drafts(cls): |
| 274 | + return PublishedQuerySet(model=cls).draft_only() |
232 | 275 |
|
233 | 276 | # Usage
|
234 |
| -all_articles = Article.objects.all() |
235 |
| -published_articles = Article.published.all() |
| 277 | +published_articles = Article.published() |
| 278 | +draft_articles = Article.drafts() |
236 | 279 | ```
|
237 | 280 |
|
238 | 281 | ## Forms
|
|
0 commit comments