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) versus User.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') versus User.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.

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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow