Django
Gestores personalizados y Querysets
Buscar..
Definiendo un administrador básico usando Querysets y el método `as_manager`
Django manger es una interfaz a través de la cual el modelo de django consulta la base de datos. El campo de objects
utilizado en la mayoría de las consultas de django es en realidad el administrador predeterminado creado por nosotros por django (esto solo se crea si no definimos administradores personalizados).
¿Por qué definiríamos un gestor / queryset personalizado?
Para evitar escribir consultas comunes en todo el código base y, en su lugar, recomendarlas utilizando una abstracción más fácil de recordar. Ejemplo: Decida usted mismo qué versión es más legible:
- Solo obtenga todos los usuarios activos:
User.objects.filter(is_active=True)
vsUser.manager.active()
- Obtenga todos los dermatólogos activos en nuestro formulario:
User.objects.filter(is_active=True).filter(is_doctor=True).filter(specialization='Dermatology')
vsUser.manager.doctors.with_specialization('Dermatology')
Otro beneficio es que si mañana decidimos que todos los psychologists
también son dermatologists
, podemos modificar fácilmente la consulta en nuestro Gerente y terminar con ella.
A continuación se muestra un ejemplo de creación de un Manager
personalizado definido mediante la creación de un QuerySet
y el uso del método 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
Lo añadiremos a nuestro modelo de la siguiente manera:
class Profile(models.Model):
...
manager = ProfileManager()
NOTA : Una vez que hayamos definido un manager
en nuestro modelo, los objects
ya no se definirán para el modelo.
select_related para todas las consultas
Modelo con ForeignKey
Trabajaremos con estos modelos:
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)
Supongamos que a menudo (siempre) accedemos a book.author.name
En vista
Podríamos usar lo siguiente, cada vez,
books = Book.objects.select_related('author').all()
Pero esto no es SECO.
Gestor personalizado
class BookManager(models.Manager):
def get_queryset(self):
qs = super().get_queryset()
return qs.select_related('author')
class Book(models.Model):
...
objects = BookManager()
Nota : la llamada a super
debe cambiarse para python 2.x
Ahora todo lo que tenemos que usar en vistas es
books = Book.objects.all()
y no se harán consultas adicionales en la plantilla / vista.
Definir gestores personalizados.
Muy a menudo sucede que se trata de modelos que tienen algo así como un campo published
. Este tipo de campos se utilizan casi siempre al recuperar objetos, por lo que se encontrará a sí mismo escribiendo algo como:
my_news = News.objects.filter(published=True)
demasiadas veces. Puedes usar administradores personalizados para lidiar con estas situaciones, de modo que luego puedas escribir algo como:
my_news = News.objects.published()
que es más agradable y más fácil de leer por otros desarrolladores también.
Cree un archivo managers.py
en el directorio de su aplicación y defina una nueva clase de 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)
use esta clase redefiniendo la propiedad de objects
en la clase modelo:
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()
Ahora puedes obtener tus noticias publicadas simplemente de esta manera:
my_news = News.objects.published()
y también puedes realizar más filtrado:
my_news = News.objects.published(title__icontains='meow')