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) vs User.manager.active()
  • Obtenga todos los dermatólogos activos en nuestro formulario: User.objects.filter(is_active=True).filter(is_doctor=True).filter(specialization='Dermatology') vs User.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.

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


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow