Django
Benutzerdefinierte Manager und Abfragesets
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)
vsUser.manager.active()
- Holen Sie sich alle aktiven Dermatologen auf unserer plaform:
User.objects.filter(is_active=True).filter(is_doctor=True).filter(specialization='Dermatology')
vsUser.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.
select_related für alle Abfragen
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')