Django
Aangepaste beheerders en querysets
Zoeken…
Een basismanager definiëren met behulp van Querysets en de methode `as_manager`
Django-kribbe is een interface waarmee het django-model de database opvraagt. De objects
veld gebruikt in de meeste Django vragen is eigenlijk de standaard manager voor ons geschapen van Django (dit wordt alleen gemaakt als we niet op maat managers definiëren).
Waarom zouden we een aangepaste manager / queryset definiëren?
Om te voorkomen dat we algemene vragen over onze codebase schrijven en ze in plaats daarvan doorverwijzen met behulp van een beter te onthouden abstractie. Voorbeeld: bepaal zelf welke versie beter leesbaar is:
- Krijg alleen alle actieve gebruikers:
User.objects.filter(is_active=True)
versusUser.manager.active()
- Krijg alle actieve dermatologen op onze
User.objects.filter(is_active=True).filter(is_doctor=True).filter(specialization='Dermatology')
:User.objects.filter(is_active=True).filter(is_doctor=True).filter(specialization='Dermatology')
versusUser.manager.doctors.with_specialization('Dermatology')
Een ander voordeel is dat als we morgen besluiten dat alle psychologists
ook dermatologists
, we de vraag eenvoudig kunnen aanpassen in onze Manager en er klaar mee zijn.
Hieronder ziet u een voorbeeld van het maken van een aangepaste Manager
gedefinieerd door een QuerySet
en de methode as_manager
gebruiken.
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
We zullen het aan ons model toevoegen zoals hieronder:
class Profile(models.Model):
...
manager = ProfileManager()
OPMERKING : Zodra we een manager
voor ons model hebben gedefinieerd, worden objects
niet meer voor het model gedefinieerd.
select_related voor alle vragen
Model met ForeignKey
We zullen met deze modellen werken:
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)
Stel dat we vaak (altijd) toegang hebben tot book.author.name
In zicht
We kunnen het volgende gebruiken, elke keer,
books = Book.objects.select_related('author').all()
Maar dit is niet DROOG.
Aangepaste manager
class BookManager(models.Manager):
def get_queryset(self):
qs = super().get_queryset()
return qs.select_related('author')
class Book(models.Model):
...
objects = BookManager()
Opmerking : de aanroep naar super
moet worden gewijzigd voor python 2.x
Nu hoeven we alleen nog maar weergaven te gebruiken
books = Book.objects.all()
en er worden geen extra vragen gesteld in sjabloon / weergave.
Definieer aangepaste managers
Heel vaak gaat het om modellen die zoiets als een published
veld hebben. Zulke velden worden bijna altijd gebruikt bij het ophalen van objecten, zodat je merkt dat je zoiets schrijft als:
my_news = News.objects.filter(published=True)
te vaak. U kunt aangepaste managers gebruiken om met deze situaties om te gaan, zodat u vervolgens iets kunt schrijven als:
my_news = News.objects.published()
wat ook leuker en gemakkelijker te lezen is door andere ontwikkelaars.
Maak een file managers.py
in uw app-directory en definieer een nieuwe 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)
gebruik deze klasse door de eigenschap objects
opnieuw te definiëren in de modelklasse:
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()
Nu kunt u uw gepubliceerde nieuws eenvoudig op deze manier krijgen:
my_news = News.objects.published()
en u kunt ook meer filteren:
my_news = News.objects.published(title__icontains='meow')