1. 自定义管理器的作用
Django 的 models.Manager
允许自定义查询逻辑,让你更方便地封装常用查询,提高代码复用性。
在你的示例中:
objects = models.Manager()
是 Django 默认的管理器,返回所有数据。published = PublishedManager()
是自定义的管理器,只返回已发布的文章 (is_published=True
)。- 这样可以通过
Article.published.all()
快速获取已发布的文章,而不影响Article.objects.all()
返回所有文章。
2. 代码解析
python
class PublishedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(is_published=True)
(1)get_queryset()
方法
- 作用 :重写
get_queryset()
,修改默认查询集(QuerySet)。 - 原理 :
super().get_queryset()
获取原始QuerySet
,然后.filter(is_published=True)
让它只返回is_published=True
的数据。
3. 使用示例
python
# 创建文章
Article.objects.create(title="草稿文章", content="这是一篇草稿", is_published=False)
Article.objects.create(title="已发布文章", content="这是一篇已发布的文章", is_published=True)
# 查询所有文章
print(Article.objects.all())
# 输出: <QuerySet [<Article: 草稿文章>, <Article: 已发布文章>]>
# 只查询已发布的文章
print(Article.published.all())
# 输出: <QuerySet [<Article: 已发布文章>]>
Article.objects.all()
返回所有文章。Article.published.all()
自动过滤掉未发布的文章。
4. 其他常见用法
(1)添加自定义方法
可以在 PublishedManager
里添加更多自定义方法,比如查询最近发布的文章:
python
class PublishedManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(is_published=True)
def recent(self, days=7):
from django.utils.timezone import now
return self.get_queryset().filter(created_at__gte=now() - timedelta(days=days))
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
is_published = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
objects = models.Manager() # 默认管理器
published = PublishedManager() # 只返回已发布的文章
使用方法
python
# 查询最近 7 天发布的文章
Article.published.recent()
(2)防止 objects
被覆盖
如果 objects
只使用 PublishedManager
,就无法查询未发布的文章:
python
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
is_published = models.BooleanField(default=False)
objects = PublishedManager() # 这样 `objects.all()` 也只返回已发布的文章
如果要查询所有文章(包括未发布的),最好保留 objects = models.Manager()
,这样:
Article.objects.all()
获取所有文章Article.published.all()
只获取已发布的文章
5. 总结
功能 | 默认管理器 objects |
自定义管理器 published |
---|---|---|
返回所有数据 | ✅ Article.objects.all() |
❌ |
只返回已发布数据 | ❌ | ✅ Article.published.all() |
可以扩展更多方法 | ❌ | ✅ Article.published.recent() |
💡 适用于哪些场景?
- 需要频繁筛选某些特定数据(如已发布文章、活跃用户)。
- 让查询更语义化 ,避免重复
filter()
。 - 避免
objects
被污染,保留所有数据的访问能力。