Поиск…


Определение базового менеджера с использованием Querysets и метода `as_manager`

Django manger - это интерфейс, через который модель django запрашивает базу данных. Поле objects используемое в большинстве запросов django, фактически является менеджером по умолчанию, созданным для нас django (это создается только в том случае, если мы не определяем настраиваемых менеджеров).

Почему мы должны определить пользовательский менеджер / набор запросов?

Чтобы избежать написания общих запросов по всей нашей базе кода и вместо этого ссылаться на них, используя более легкую для запоминания абстракцию. Пример. Определите, какая версия более читаема:

  • Только получить всех активных пользователей: User.objects.filter(is_active=True) vs User.manager.active()
  • Получить всех активных дерматологов на нашей платформе: User.objects.filter(is_active=True).filter(is_doctor=True).filter(specialization='Dermatology') vs User.manager.doctors.with_specialization('Dermatology')

Еще одно преимущество заключается в том, что если завтра мы решаем, что все psychologists также являются dermatologists , мы можем легко изменить запрос в нашем Менеджере и сделать с ним.

Ниже приведен пример создания настраиваемого Manager определяется путем создания QuerySet и использования метода as_manager .

from django.db.models.query import QuerySet

class ProfileQuerySet(QuerySet):
    def doctors(self):
        return self.filter(user_type="Doctor", user__is_active=True)

    def with_specializations(self, specialization):
        return self.filter(specializations=specialization)

    def users(self):
        return self.filter(user_type="Customer", user__is_active=True)

ProfileManager = ProfileQuerySet.as_manager

Мы добавим его в нашу модель, как показано ниже:

class Profile(models.Model):
    ...
    manager = ProfileManager()

ПРИМЕЧАНИЕ . Как только мы определили manager на нашей модели, objects больше не будут определены для модели.

Модель с ForeignKey

Мы будем работать с этими моделями:

from django.db import models

class Book(models.Model):
 name= models.CharField(max_length=50)
 author = models.ForeignKey(Author)

class Author(models.Model):
 name = models.CharField(max_length=50)

Предположим, что мы часто (всегда) book.author.name доступ к book.author.name

Ввиду

Мы могли бы использовать следующее, каждый раз,

books = Book.objects.select_related('author').all()

Но это не СУХОЙ.

Пользовательский менеджер

class BookManager(models.Manager):

    def get_queryset(self):
        qs = super().get_queryset()
        return qs.select_related('author')

class Book(models.Model):
    ...
    objects = BookManager()

Примечание : вызов super должен быть изменен для python 2.x

Теперь все, что нам нужно использовать в представлениях

books = Book.objects.all()

и никаких дополнительных запросов в шаблоне / представлении не будет.

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

Очень часто приходится иметь дело с моделями, которые имеют что-то вроде published области. Такие типы полей почти всегда используются при извлечении объектов, так что вы обнаружите, что пишете что-то вроде:

my_news = News.objects.filter(published=True)

слишком много раз. Вы можете использовать пользовательских менеджеров для решения этих ситуаций, чтобы затем вы могли написать что-то вроде:

my_news = News.objects.published()

который является более приятным и легким для чтения другими разработчиками.

Создайте файл managers.py в каталоге приложения, и определить новый models.Manager класс:

from django.db import models


class NewsManager(models.Manager):

    def published(self, **kwargs):
        # the method accepts **kwargs, so that it is possible to filter
        # published news
        # i.e: News.objects.published(insertion_date__gte=datetime.now)
        return self.filter(published=True, **kwargs)

используйте этот класс, переопределив свойство objects в классе модели:

from django.db import models

# import the created manager
from .managers import NewsManager

class News(models.Model):
    """ News model
    """
    insertion_date = models.DateTimeField('insertion date', auto_now_add=True)
    title = models.CharField('title', max_length=255)
    # some other fields here
    published = models.BooleanField('published')

    # assign the manager class to the objects property
    objects = NewsManager()

Теперь вы можете получить опубликованные новости просто так:

my_news = News.objects.published()

и вы также можете выполнять большую фильтрацию:

my_news = News.objects.published(title__icontains='meow')


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow