Suche…


Definieren eines Basismanagers mit Querysets und `as_manager`-Methode

Django-Manager ist eine Schnittstelle, über die das Django-Modell die Datenbank abfragt. Die objects Feld in den meisten django - Abfragen verwendet wird , ist eigentlich der Standard - Manager für uns von django erstellt (dies wird nur erstellt , wenn wir keine benutzerdefinierten Manager definieren).

Warum sollten wir einen benutzerdefinierten Manager / Queryset definieren?

Um zu vermeiden, dass häufige Abfragen in der gesamten Codebase geschrieben werden und stattdessen auf eine einfachere Abstraktion verwiesen wird. Beispiel: Entscheiden Sie selbst, welche Version lesbarer ist:

  • User.objects.filter(is_active=True) nur alle aktiven Benutzer: User.objects.filter(is_active=True) vs User.manager.active()
  • Holen Sie sich alle aktiven Dermatologen auf unserer plaform: User.objects.filter(is_active=True).filter(is_doctor=True).filter(specialization='Dermatology') vs User.manager.doctors.with_specialization('Dermatology')

Ein weiterer Vorteil ist, dass, wenn wir morgen entscheiden, dass alle psychologists auch dermatologists , wir die Abfrage in unserem Manager leicht modifizieren und damit erledigen können.

Im Folgenden finden Sie ein Beispiel zum Erstellen eines benutzerdefinierten Manager , der durch Erstellen eines QuerySet und Verwenden der as_manager Methode definiert wird.

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

Wir werden es wie folgt zu unserem Modell hinzufügen:

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

HINWEIS : Wenn wir einen manager für unser Modell definiert haben, werden objects nicht mehr für das Modell definiert.

Modell mit ForeignKey

Wir werden mit diesen Modellen arbeiten:

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)

Angenommen, wir greifen häufig (immer) auf book.author.name

Im Hinblick auf

Wir könnten jedes Mal folgendes verwenden:

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

Dies ist jedoch nicht trocken.

Benutzerdefinierter Manager

class BookManager(models.Manager):

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

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

Hinweis : Der Aufruf von super muss für Python 2.x geändert werden

Jetzt müssen wir nur noch Ansichten verwenden

books = Book.objects.all()

Es werden keine zusätzlichen Abfragen in der Vorlage / Ansicht gemacht.

Definieren Sie benutzerdefinierte Manager

Sehr oft passiert es mit Modellen, die so etwas wie ein published Feld haben. Diese Art von Feldern wird fast immer beim Abrufen von Objekten verwendet, so dass Sie sich wie folgt schreiben werden:

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

Zu viel zeit. Sie können benutzerdefinierte Manager verwenden, um mit diesen Situationen umzugehen, sodass Sie dann Folgendes schreiben können:

my_news = News.objects.published()

Das ist schöner und auch von anderen Entwicklern leichter zu lesen.

Erstellen Sie eine Datei managers.py in der App - Verzeichnis und definieren eine neue models.Manager Klasse:

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)

Verwenden Sie diese Klasse durch die Neudefinition objects Eigenschaft in der Modellklasse:

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

Jetzt können Sie Ihre veröffentlichten Nachrichten einfach auf folgende Weise erhalten:

my_news = News.objects.published()

und Sie können auch mehr filtern:

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


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow