Sök…


Definiera en bashanterare med Querysets och metoden 'as_manager'

Django manger är ett gränssnitt genom vilket django-modellen frågar databasen. objects som används i de flesta djangofrågor är faktiskt standardhanteraren som skapats för oss av django (detta skapas endast om vi inte definierar anpassade chefer).

Varför skulle vi definiera en anpassad manager / frågeställning?

För att undvika att skriva vanliga frågor över hela vår kodbas och i stället hänvisa dem med en lättare att komma ihåg abstraktion. Exempel: Bestäm själv vilken version som är mer läsbar:

  • User.objects.filter(is_active=True) bara alla aktiva användare: User.objects.filter(is_active=True) vs User.manager.active()
  • Få alla aktiva hudläkare på vår plattform: User.objects.filter(is_active=True).filter(is_doctor=True).filter(specialization='Dermatology') vs User.manager.doctors.with_specialization('Dermatology')

En annan fördel är att om vi i morgon bestämmer att alla psychologists också är dermatologists , kan vi enkelt ändra frågan i vår chef och göra det med det.

Nedan är ett exempel på att skapa en anpassad Manager definierad genom att skapa en QuerySet och använda metoden 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

Vi lägger till den till vår modell enligt nedan:

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

OBS : När vi har definierat en manager på vår modell kommer inte objects att definieras längre för modellen.

Modell med ForeignKey

Vi kommer att arbeta med dessa modeller:

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)

Anta att vi ofta (alltid) kommer åt book.author.name

Med tanke

Vi kunde använda följande, varje gång,

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

Men detta är inte TÖR.

Anpassad chef

class BookManager(models.Manager):

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

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

Obs : samtalet till super måste ändras för python 2.x

Nu är allt vi behöver använda i vyer

books = Book.objects.all()

och inga ytterligare frågor kommer att göras i mall / vy.

Definiera anpassade chefer

Mycket ofta händer det med modeller som har något som ett published fält. Sådana fält används nästan alltid när du hämtar objekt, så att du hittar dig själv att skriva något som:

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

för många gånger. Du kan använda anpassade chefer för att hantera dessa situationer, så att du sedan kan skriva något som:

my_news = News.objects.published()

vilket också är trevligare och lättare att läsa av andra utvecklare.

Skapa en fil managers.py i din app katalogen och definiera en ny models.Manager klass:

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)

använd den här klassen genom att omdefiniera objects egenskaper i modellklassen:

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 kan du få dina publicerade nyheter helt enkelt på detta sätt:

my_news = News.objects.published()

och du kan också utföra mer filtrering:

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


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow