Django
Gestionnaires et ensembles de requêtes personnalisés
Recherche…
Définition d'un gestionnaire de base à l'aide de la méthode Querysets et de la méthode `as_manager`
Django manger est une interface par laquelle le modèle django interroge la base de données. Le champ d' objects
utilisé dans la plupart des requêtes django est en fait le gestionnaire par défaut créé par django (il est créé uniquement si nous ne définissons pas de gestionnaires personnalisés).
Pourquoi définirions-nous un gestionnaire / groupe de requête personnalisé?
Pour éviter d'écrire des requêtes communes sur notre base de code et de les renvoyer à l'aide d'une abstraction plus facile à retenir. Exemple: Décidez pour vous-même quelle version est la plus lisible:
-
User.objects.filter(is_active=True)
que tous les utilisateurs actifs:User.objects.filter(is_active=True)
vsUser.manager.active()
- Obtenez tous les dermatologues actifs sur notre plateforme:
User.objects.filter(is_active=True).filter(is_doctor=True).filter(specialization='Dermatology')
vsUser.manager.doctors.with_specialization('Dermatology')
Un autre avantage est que si demain nous décidons que tous les psychologists
sont aussi des dermatologists
, nous pouvons facilement modifier la requête dans notre gestionnaire et en finir avec elle.
Vous trouverez ci-dessous un exemple de création d'un Manager
personnalisé défini en créant un QuerySet
et en utilisant la méthode 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
Nous allons l'ajouter à notre modèle comme ci-dessous:
class Profile(models.Model):
...
manager = ProfileManager()
REMARQUE : Une fois que nous avons défini un manager
sur notre modèle, les objects
ne seront plus définis pour le modèle.
select_related pour toutes les requêtes
Modèle avec ForeignKey
Nous allons travailler avec ces modèles:
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)
Supposons que nous book.author.name
souvent (toujours) à book.author.name
En vue
Nous pourrions utiliser ce qui suit à chaque fois
books = Book.objects.select_related('author').all()
Mais ce n'est pas sec.
Gestionnaire personnalisé
class BookManager(models.Manager):
def get_queryset(self):
qs = super().get_queryset()
return qs.select_related('author')
class Book(models.Model):
...
objects = BookManager()
Note : l'appel à super
doit être changé pour python 2.x
Maintenant, tout ce que nous devons utiliser dans les vues est
books = Book.objects.all()
et aucune requête supplémentaire ne sera faite dans un modèle / vue.
Définir des gestionnaires personnalisés
Très souvent, il s'agit de modèles qui ont quelque chose comme un champ published
. Ces types de champs sont presque toujours utilisés lors de la récupération d'objets, de sorte que vous vous retrouvez à écrire quelque chose comme:
my_news = News.objects.filter(published=True)
trop de fois. Vous pouvez utiliser des gestionnaires personnalisés pour gérer ces situations, de sorte que vous puissiez ensuite écrire quelque chose comme:
my_news = News.objects.published()
ce qui est plus agréable et plus facile à lire par les autres développeurs.
Créez un fichier managers.py
dans votre répertoire d'application et définissez une nouvelle classe 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)
utilisez cette classe en redéfinissant la propriété objects
dans la classe de modèle:
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()
Maintenant, vous pouvez obtenir vos nouvelles publiées simplement de cette manière:
my_news = News.objects.published()
et vous pouvez également effectuer plus de filtrage:
my_news = News.objects.published(title__icontains='meow')