Класс Manager

Класс Manager является интерфейсом между моделью и базой данных. Он предоставляет методы для создания, чтения, обновления и удаления записей. По умолчанию каждая модель получает менеджер с именем objects, который содержит базовый набор методов для работы с QuerySet. Вы можете создавать собственные менеджеры для добавления специфической логики запросов или изменения стандартного поведения.

Стандартный менеджер

Рассмотрим использование стандартного менеджера objects для выполнения базовых операций с моделью:

pythonfrom myapp.models import Article

# Создание записи
article = Article.objects.create(
  title="Django Manager",
  status="draft"
)

# Получение всех записей
all_articles = Article.objects.all()
print(all_articles)

Результат выполнения кода:

python[<Article: Django Manager>]

Кастомный менеджер

Создадим собственный менеджер для добавления часто используемых фильтров. Менеджер наследуется от Manager и добавляет методы, возвращающие QuerySet с определенными условиями:

pythonfrom django.db import models

class ArticleManager(models.Manager):
  def published(self):
    return self.filter(status="published")

  def recent(self, days=7):
    from datetime import timedelta
    from django.utils import timezone

    cutoff_date = timezone.now() - timedelta(days=days)
    return self.filter(created_at__gte=cutoff_date)

class Article(models.Model):
  title = models.CharField(max_length=200)
  status = models.CharField(max_length=20)
  created_at = models.DateTimeField(auto_now_add=True)
  
  objects = ArticleManager()

Теперь можно использовать эти методы для получения отфильтрованных записей:

pythonfrom myapp.models import Article

# Получаем только опубликованные статьи
published = Article.objects.published()
print(published)

# Получаем статьи за последние 3 дня
recent_articles = Article.objects.recent(days=3)
print(recent_articles)

Результат выполнения кода:

python[<Article: Первая статья>, <Article: Вторая статья>]
[<Article: Вторая статья>]

Переопределение базового QuerySet

Можно переопределить метод get_queryset для изменения набора записей по умолчанию. Это полезно для фильтрации мягко удаленных записей или применения постоянных условий:

pythonfrom django.db import models

class ActiveManager(models.Manager):
  def get_queryset(self):
    return super().get_queryset().filter(is_active=True)

class Product(models.Model):
  name = models.CharField(max_length=100)
  is_active = models.BooleanField(default=True)
  price = models.IntegerField()

  # Менеджер для активных товаров
  active_objects = ActiveManager()
  
  # Стандартный менеджер для всех товаров
  objects = models.Manager()

При использовании active_objects автоматически применяется фильтрация по активным записям:

pythonfrom myapp.models import Product

# Получаем только активные товары
active_products = Product.active_objects.all()
print(active_products)

# Получаем все товары, включая неактивные
all_products = Product.objects.all()
print(all_products)

Результат выполнения кода:

python[<Product: Ноутбук>, <Product: Мышь>]
[<Product: Ноутбук>, <Product: Мышь>, <Product: Клавиатура>]

Комбинирование методов менеджера

Методы менеджера можно комбинировать в цепочки для построения сложных запросов. Каждый метод возвращает QuerySet, что позволяет применять дополнительные фильтры:

pythonfrom myapp.models import Article

# Комбинируем методы опубликованных и недавних статей
recent_published = Article.objects.published().recent(days=7)
print(recent_published)

# Добавляем дополнительную фильтрацию
high_rated = recent_published.filter(rating__gte=4)
print(high_rated)

Результат выполнения кода:

python[<Article: Статья о Django>, <Article: Статья о Python>]
[<Article: Статья о Django>]

Использование нескольких менеджеров

Модель может иметь несколько менеджеров для разных целей. Это позволяет разделить логику запросов по разным контекстам использования:

pythonfrom django.db import models

class UserManager(models.Manager):
  def active(self):
    return self.filter(is_active=True)

  def admin(self):
    return self.filter(is_staff=True)

class User(models.Model):
  username = models.CharField(max_length=100)
  email = models.EmailField()
  is_active = models.BooleanField(default=True)
  is_staff = models.BooleanField(default=False)

  # Несколько менеджеров для разных контекстов
  users = UserManager()
  active_users = UserManager().active()

Рассмотрим пример использования разных менеджеров:

pythonfrom myapp.models import User

# Все активные пользователи
active = User.users.active()
print(active)

# Пользователи с правами администратора
admins = User.users.admin()
print(admins)

# Активные администраторы
active_admins = User.active_users.admin()
print(active_admins)

Результат выполнения кода:

python[<User: john_doe>, <User: admin>]
[<User: admin>]
[<User: admin>]

Смотрите также

  • атрибут objects,
    который является стандартным менеджером модели
  • метод get_queryset,
    который возвращает базовый QuerySet менеджера
  • метод all,
    который возвращает все записи из QuerySet
  • метод filter,
    который фильтрует записи в QuerySet