Django
Anpassade chefer och frågeställningar
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)
vsUser.manager.active()
- Få alla aktiva hudläkare på vår plattform:
User.objects.filter(is_active=True).filter(is_doctor=True).filter(specialization='Dermatology')
vsUser.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.
select_related för alla frågor
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')