Szukaj…


Definiowanie podstawowego menedżera za pomocą zestawów zapytań i metody `as_manager`

Menedżer Django to interfejs, przez który model django wysyła zapytanie do bazy danych. Pole objects używane w większości zapytań django jest tak naprawdę domyślnym menedżerem utworzonym dla nas przez django (jest on tworzony tylko wtedy, gdy nie zdefiniujemy niestandardowych menedżerów).

Dlaczego mielibyśmy definiować niestandardowego menedżera / zestaw zapytań?

Aby uniknąć pisania typowych zapytań w całej naszej bazie kodu i zamiast tego odsyłania ich za pomocą łatwiejszej do zapamiętania abstrakcji. Przykład: sam zdecyduj, która wersja jest bardziej czytelna:

  • User.objects.filter(is_active=True) tylko wszystkich aktywnych użytkowników: User.objects.filter(is_active=True) vs User.manager.active()
  • Pobierz wszystkich aktywnych dermatologów na naszej platformie: User.objects.filter(is_active=True).filter(is_doctor=True).filter(specialization='Dermatology') vs User.manager.doctors.with_specialization('Dermatology')

Kolejną korzyścią jest to, że jeśli jutro zdecydujemy, że wszyscy psychologists są również dermatologists , możemy łatwo zmodyfikować zapytanie w naszym menedżerze i wykonać to.

Poniżej znajduje się przykład tworzenia niestandardowego Manager zdefiniowanego przez utworzenie QuerySet i użycie metody 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

Dodamy go do naszego modelu, jak poniżej:

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

UWAGA : Po zdefiniowaniu manager w naszym modelu, objects nie będą już definiowane dla modelu.

Model z ForeignKey

Będziemy pracować z tymi modelami:

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)

Załóżmy, że często (zawsze) uzyskujemy dostęp do book.author.name

Z uwagi

Za każdym razem możemy skorzystać z następujących

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

Ale to nie jest SUCHE.

Menedżer niestandardowy

class BookManager(models.Manager):

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

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

Uwaga : wywołanie super musi być zmienione dla Pythona 2.x

Teraz wszystko, czego musimy użyć w widokach, to

books = Book.objects.all()

i nie będzie żadnych dodatkowych zapytań w szablonie / widoku.

Zdefiniuj niestandardowych menedżerów

Bardzo często zdarza się, że mamy do czynienia z modelami, które mają coś w rodzaju published pola. Tego rodzaju pola są prawie zawsze używane podczas wyszukiwania obiektów, dzięki czemu można znaleźć coś takiego:

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

zbyt wiele razy. Możesz użyć niestandardowych menedżerów, aby poradzić sobie z tymi sytuacjami, aby następnie napisać coś takiego:

my_news = News.objects.published()

który jest ładniejszy i łatwiejszy do odczytania również przez innych programistów.

Utwórz plik managers.py w katalogu aplikacji i zdefiniuj nową klasę 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)

użyj tej klasy, ponownie definiując właściwość objects w klasie modelu:

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()

Teraz możesz otrzymywać publikowane wiadomości w ten sposób:

my_news = News.objects.published()

i możesz także wykonać więcej filtrowania:

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


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow