0 day streak
python / intermediate
Snippet

Django Custom Model Manager and QuerySet Methods

This pattern shows how to create reusable QuerySet methods by chaining them through a custom Manager. The PublishedQuerySet class encapsulates query logic in reusable methods that can be chained together. The ArticleManager delegates to this QuerySet while exposing a clean API. This approach keeps query logic modular and testable.

snippet.py
python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from django.db import models
class PublishedQuerySet(models.QuerySet):
def published(self):
return self.filter(status='published')
def in_date_range(self, start, end):
return self.filter(published_date__range=[start, end])
def by_author(self, author):
return self.filter(author=author)
def with_min_views(self, min_views):
return self.filter(view_count__gte=min_views)
class ArticleManager(models.Manager):
def get_queryset(self):
return PublishedQuerySet(self.model, using=self._db)
def published(self):
return self.get_queryset().published()
def with_min_views(self, min_views):
return self.get_queryset().with_min_views(min_views)
class Article(models.Model):
title = models.CharField(max_length=200)
author = models.ForeignKey(User, on_delete=models.CASCADE)
status = models.CharField(max_length=20, default='draft')
published_date = models.DateTimeField(null=True)
view_count = models.IntegerField(default=0)
content = models.TextField()
objects = ArticleManager()
class Meta:
ordering = ['-published_date']
django
Breakdown
1
class PublishedQuerySet(models.QuerySet):
Define custom QuerySet class inheriting from models.QuerySet
2
def published(self):
Filter method returning only published articles
3
return self.filter(status='published')
Chain filter onto the QuerySet and return it
4
def in_date_range(self, start, end):
Date range filter method with start and end parameters
5
def by_author(self, author):
Method to filter articles by specific author instance
6
class ArticleManager(models.Manager):
Custom manager class inheriting from models.Manager
7
return PublishedQuerySet(self.model, using=self._db)
Override get_queryset to return custom QuerySet with proper database routing
8
objects = ArticleManager()
Assign custom manager as the default manager for the model