django model Manager

🧩 一、Manager 是什么?

Manager 是 Django ORM 提供的数据库操作接口。

每个模型(Model)默认都有一个管理器 objects,用于执行所有数据库查询。

python 复制代码
class Article(models.Model):
    title = models.CharField(max_length=100)

# 默认存在一个 Manager
Article.objects.all()      # 查询所有文章
Article.objects.filter(...)  # 过滤

✅ Django 在每个 Model 类中自动添加一个 objects = models.Manager()

你可以通过它访问 ORM 提供的所有方法(filter(), get(), create(), update(), 等)。


🧠 二、Manager 的主要作用

功能 示例
定义默认查询范围 限制返回的对象(如只显示已发布内容)
添加自定义查询方法 封装复杂查询逻辑
控制默认行为 指定模型默认返回什么数据
逻辑复用 让过滤逻辑集中,不重复写在 view 或 service 里

⚙️ 三、定义自定义 Manager

✅ 基本结构

python 复制代码
from django.db import models

class PublishedManager(models.Manager):
    def get_queryset(self):
        # 定义默认返回的数据范围
        return super().get_queryset().filter(is_published=True)

然后在模型中使用它:

python 复制代码
class Article(models.Model):
    title = models.CharField(max_length=100)
    is_published = models.BooleanField(default=False)

    # 默认管理器
    objects = models.Manager()
    # 自定义管理器
    published = PublishedManager()

📖 使用效果:

python 复制代码
Article.objects.all()        # 所有文章
Article.published.all()      # 只返回已发布的文章

🧩 四、get_queryset() 方法详解

get_queryset() 是 Manager 的核心方法,用来定义默认查询集(QuerySet)

Django 的所有 ORM 操作最终都是基于这个 QuerySet。

示例:

python 复制代码
class ActiveUserManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(is_active=True)

使用:

python 复制代码
User.active.all()     # 只返回活跃用户
User.objects.all()    # 所有用户

🔧 五、添加自定义查询方法

你可以在 Manager 中添加业务逻辑方法

python 复制代码
class ArticleManager(models.Manager):
    def published(self):
        return self.get_queryset().filter(is_published=True)

    def recent(self):
        return self.get_queryset().order_by('-created_at')[:5]

使用:

python 复制代码
Article.objects.published()       # 只返回发布的文章
Article.objects.published().recent()  # 最近5篇已发布文章

💡 六、与自定义 QuerySet 结合使用(推荐做法)

Django 推荐将复杂查询逻辑放入自定义 QuerySet,再让 Manager 使用它。

python 复制代码
class ArticleQuerySet(models.QuerySet):
    def published(self):
        return self.filter(is_published=True)

    def recent(self):
        return self.order_by('-created_at')

然后定义 Manager:

python 复制代码
class ArticleManager(models.Manager):
    def get_queryset(self):
        return ArticleQuerySet(self.model, using=self._db)

    # 让 Manager 支持链式调用
    def published(self):
        return self.get_queryset().published()

模型:

python 复制代码
class Article(models.Model):
    title = models.CharField(max_length=100)
    is_published = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)

    objects = ArticleManager()

📖 调用:

python 复制代码
Article.objects.published().recent()

✅ 优点:

  • 支持链式调用
  • QuerySet 与 Manager 逻辑分层更清晰
  • 更容易测试与复用

🧱 七、多个 Manager 的应用场景

你可以为同一个模型定义多个 Manager,用于不同业务场景:

python 复制代码
class Article(models.Model):
    title = models.CharField(max_length=100)
    is_published = models.BooleanField(default=False)

    objects = models.Manager()       # 默认管理器
    published = PublishedManager()   # 只看发布的

🔐 八、Manager 与默认行为

  • Django 的通用视图(如 ListView)默认使用模型的 第一个定义的 Manager
  • 如果你想让某个自定义 Manager 成为默认管理器,只需把它放在第一个位置:
python 复制代码
class Article(models.Model):
    published = PublishedManager()   # 默认被使用
    objects = models.Manager()

🧰 九、实际应用案例

✅ 示例1:用户权限过滤

python 复制代码
class UserQuerySet(models.QuerySet):
    def active(self):
        return self.filter(is_active=True)
    
    def staff(self):
        return self.filter(is_staff=True)

class UserManager(models.Manager):
    def get_queryset(self):
        return UserQuerySet(self.model, using=self._db)

    def active(self):
        return self.get_queryset().active()
python 复制代码
User.objects.active().staff()

✅ 示例2:软删除模型

python 复制代码
class SoftDeleteManager(models.Manager):
    def get_queryset(self):
        return super().get_queryset().filter(is_deleted=False)

class Post(models.Model):
    title = models.CharField(max_length=100)
    is_deleted = models.BooleanField(default=False)

    objects = SoftDeleteManager()
    all_objects = models.Manager()  # 可访问已删除的

🧭 十、Manager 与 signals、admin、views 的结合

在 admin 中使用自定义 Manager:

python 复制代码
class ArticleAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        return Article.published.all()

在 views 中使用:

python 复制代码
def index(request):
    articles = Article.objects.published().recent()
    return render(request, 'index.html', {'articles': articles})

✅ 总结表

概念 作用
Manager ORM 查询接口,用于操作数据库
get_queryset() 定义默认查询集
自定义方法 封装业务查询逻辑
自定义 QuerySet 支持链式调用、逻辑复用
多个 Manager 用于区分不同数据视图(如软删除、发布状态)
相关推荐
IvorySQL11 小时前
PG 日报|新增 VACUUM 全维度统计信息补丁迭代
数据库·人工智能·postgresql·ivorysql
白露与泡影13 小时前
Redis 缓存实战:雪崩、穿透、击穿一次讲透
数据库·redis·缓存
赵渝强老师14 小时前
【赵渝强老师】使用Oracle可传输的表空间迁移数据
数据库·oracle
IpdataCloud15 小时前
跨区服玩家延迟高怎么办?用IP离线库自动分配到最近服务器
数据库·tcp/ip·github·php·ip
wuqingshun31415916 小时前
MYSQL默认的事务隔离级别是什么?为什么选择这个级别?
数据库·mysql
空中湖17 小时前
电池简史(五):极限之梦与终章——锂硫、锂空气、量子电池,以及你该知道的电池投资与生活指南
数据库·程序人生
蓝胖子酱18 小时前
在 Electron 中用 electron-store 实现加密存储与自定义格式文件
前端·javascript·数据库
snow@li19 小时前
Redis:数据库语法速查表 / 全景梳理
数据库·redis·缓存
Devlive 开源社区19 小时前
Nebula 1.6.0 发布:跨区域桶自动路由、秒传、文本/PDF 预览一次到位
数据库·sql
这个DBA有点耶19 小时前
导个数据中文全变问号?字符集这事儿真没那么简单
数据库·mysql·代码规范