【后端】【django】【进阶】自定义管理器——封装常用查询

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 被污染,保留所有数据的访问能力
相关推荐
TDengine (老段)37 分钟前
TDengine taosAdapter — 多协议网关详解
大数据·数据库·物联网·时序数据库·iot·tdengine·涛思数据
Nturmoils37 分钟前
SQL Server 迁移到 KingbaseES:一次复杂 BI 查询的性能实测
数据库
今天AI了吗2 小时前
MCP 协议打通 AI 与国产数据库,SQL 调优全流程一站式闭环
数据库·人工智能·sql
灯澜忆梦2 小时前
【MySQL11】进阶篇 | 索引_#3使用规则
数据库·sql·mysql·性能优化
名字还没想好☜2 小时前
Go 的 sync.Cond 实战:用条件变量做等待/通知,比忙轮询省 CPU
开发语言·数据库·后端·golang·go
wWYy.2 小时前
Mysql:有哪些锁?
数据库·mysql
李可以量化2 小时前
Tornado 从了解到精通(一)下:异步与非阻塞 IO 核心原理
java·数据库·tornado
VALENIAN瓦伦尼安教学设备3 小时前
ASHOOTER激光对中仪如何通过颜色确定调整是否合适
数据库·嵌入式硬件·算法
Wang's Blog3 小时前
AI Agent白手起家58: 项目可观测性——用 LangSmith 实现全链路追踪
数据库·人工智能
SL_staff4 小时前
JVS数字底座实践:如何复用企业文档能力快速构建知识类应用
java·数据库·程序员