Vous êtes sur la page 1sur 8

Django

Documentação

Gerentes
class Manager[source]

A Manageré a interface através da qual as operações de consulta do banco de dados são fornecidas aos modelos do Django. Pelo menos um Managerexiste para cada modelo em um
aplicativo Django.

A forma como as Managerclasses funcionam está documentada em Fazer consultas ; Este documento toca especi camente nas opções do modelo que personalizam o Manager
comportamento.

Nomes do gerente
Por padrão, o Django adiciona um Managercom o nome objectsa cada classe de modelo do Django. No entanto, se você quiser usar objectscomo um nome de campo ou se quiser
usar um nome diferente objectsdo Manager, poderá renomeá-lo por modelo. Para renomear o Managerpara uma determinada classe, de na um atributo de classe do tipo
models.Manager()nesse modelo. Por exemplo:

from django.db import models

class Person(models.Model):
#...
people = models.Manager()

Usando este modelo de exemplo, Person.objectsirá gerar uma AttributeErrorexceção, mas Person.people.all()fornecerá uma lista de todos os Personobjetos.

Gerenciadores personalizados
Você pode usar um personalizado Managerem um determinado modelo estendendo a Managerclasse base e instanciando seu personalizado Managerem seu modelo.

Há dois motivos pelos quais você pode querer personalizar um Manager: para adicionar Managermétodos extras e / ou modi car QuerySetos Manager retornos iniciais .

Adicionando métodos extras de gerenciador


A adição de Managermétodos extras é a maneira preferida de adicionar a funcionalidade "nível de tabela" aos seus modelos. (Para funcionalidade "nível de linha" - ou seja, funções que
atuam em uma única instância de um objeto de modelo - use métodos Model , não Managermétodos personalizados .)

Um Managermétodo personalizado pode retornar o que você quiser. Não precisa retornar a QuerySet.

Por exemplo, esse personalizado Manageroferece um método with_counts(), que retorna uma lista de todos os OpinionPollobjetos, cada um com um num_responsesatributo
extra que é o resultado de uma consulta agregada:

Idioma: en

Versão da documentação: 2.1


from django.db import models

class PollManager(models.Manager):
def with_counts(self):
from django.db import connection
with connection.cursor() as cursor:
cursor.execute("""
SELECT p.id, p.question, p.poll_date, COUNT(*)
FROM polls_opinionpoll p, polls_response r
WHERE p.id = r.poll_id
GROUP BY p.id, p.question, p.poll_date
ORDER BY p.poll_date DESC""")
result_list = []
for row in cursor.fetchall():
p = self.model(id=row[0], question=row[1], poll_date=row[2])
p.num_responses = row[3]
result_list.append(p)
return result_list

class OpinionPoll(models.Model):
question = models.CharField(max_length=200)
poll_date = models.DateField()
objects = PollManager()

class Response(models.Model):
poll = models.ForeignKey(OpinionPoll, on_delete=models.CASCADE)
person_name = models.CharField(max_length=50)
response = models.TextField()

Com este exemplo, você usaria OpinionPoll.objects.with_counts()para retornar essa lista de OpinionPollobjetos com num_responsesatributos.

Outra coisa a observar sobre esse exemplo é que os Managermétodos podem acessar self.modelpara obter a classe de modelo à qual estão anexados.

Modi cando a inicial do gerente QuerySet


A Managerbase de a QuerySetretorna todos os objetos no sistema. Por exemplo, usando este modelo:

from django.db import models

class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)

… A declaração Book.objects.all()retornará todos os livros no banco de dados.

Você pode sobrescrever a Managerbase QuerySetsubstituindo o Manager.get_queryset()método. get_queryset()deve retornar um QuerySetcom as propriedades
necessárias.

Por exemplo, o modelo a seguir tem dois Manager s - um que retorna todos os objetos e um que retorna apenas os livros de Roald Dahl:

# First, define the Manager subclass.


class DahlBookManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(author='Roald Dahl')

# Then hook it into the Book model explicitly.


class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)

objects = models.Manager() # The default manager.


dahl_objects = DahlBookManager() # The Dahl-specific manager.

Com este modelo de amostra, Book.objects.all()retornará todos os livros no banco de dados, mas Book.dahl_objects.all()só retornará os escritos por Roald Dahl.
Idioma: en

Claro, porque get_queryset()retorna um QuerySetobjeto, você pode usar filter(), exclude()e todos os outros QuerySetmétodos nele. Então, essas declarações são todas
legais: Versão da documentação: 2.1
Book.dahl_objects.all()
Book.dahl_objects.filter(title='Matilda')
Book.dahl_objects.count()

Este exemplo também apontou outra técnica interessante: usar vários gerenciadores no mesmo modelo. Você pode anexar quantas Manager()instâncias a um modelo desejar. Essa é
uma maneira fácil de de nir " ltros" comuns para seus modelos.

Por exemplo:

class AuthorManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(role='A')

class EditorManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(role='E')

class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
role = models.CharField(max_length=1, choices=(('A', _('Author')), ('E', _('Editor'))))
people = models.Manager()
authors = AuthorManager()
editors = EditorManager()

Este exemplo permite que você solicite Person.authors.all(), Person.editors.all()e Person.people.all(), produzindo resultados previsíveis.

Gerenciadores padrão

Model._default_manager

Se você usar Managerobjetos personalizados , observe que o primeiro Manager encontro do Django (na ordem em que eles estão de nidos no modelo) tem um status especial. O
Django interpreta o primeiro Managerde nido em uma classe como o "padrão" Manager, e várias partes do Django (incluindo dumpdata) usarão Managerexclusivamente para esse
modelo. Como resultado, é uma boa ideia ter cuidado na escolha do gerente padrão para evitar uma situação em que a substituição de get_queryset()resultados impossibilite a
recuperação de objetos com os quais você gostaria de trabalhar.

Você pode especi car um gerenciador padrão personalizado usando Meta.default_manager_name.

Se você estiver escrevendo algum código que deve manipular um modelo desconhecido, por exemplo, em um aplicativo de terceiros que implemente uma exibição genérica, use esse
gerenciador (ou _base_manager) em vez de assumir que o modelo possui um objects gerenciador.

Gerentes de base

Model._base_manager

Usando gestores de acesso objeto relacionado

Por padrão, o Django usa uma instância da Model._base_managerclasse manager ao acessar objetos relacionados (ie choice.question), não o _default_managerobjeto
relacionado. Isso ocorre porque o Django precisa ser capaz de recuperar o objeto relacionado, mesmo que, de outra forma, fosse ltrado (e, portanto, inacessível) pelo gerenciador
padrão.

Se a classe de gerenciador de base normal ( django.db.models.Manager) não for apropriada para suas circunstâncias, você pode dizer ao Django qual classe usar por con guração
Meta.base_manager_name.

Os gerentes de base não são usados ao consultar modelos relacionados. Por exemplo, se o Questionmodelo do tutorial tivesse um deleted campo e um gerenciador de base que
ltrasse instâncias com deleted=True, um tipo de Choice.objects.filter(question__name__startswith='What') consulta incluiria opções relacionadas a perguntas
excluídas.

Não ltre quaisquer resultados nesse tipo de subclasse de gerenciador

Esse gerenciador é usado para acessar objetos relacionados de algum outro modelo. Nessas situações, o Django tem que ser capaz de ver todos os objetos para o modelo que está
buscando, para que qualquer coisa que é referida possa ser recuperada.
Idioma: en
Se você substituir o get_queryset()método e ltrar quaisquer linhas, o Django retornará resultados incorretos. Não faça isso. Um gerente que ltre os resultados
get_queryset()não é apropriado para uso como gerenciador de base.
Versão da documentação: 2.1
Chamando QuerySetmétodos customizados do gerenciador
Embora a maioria dos métodos do padrão QuerySetseja acessível diretamente do Manager, esse é o caso apenas dos métodos extras de nidos em um custom QuerySetse você
também os implementar no Manager:

class PersonQuerySet(models.QuerySet):
def authors(self):
return self.filter(role='A')

def editors(self):
return self.filter(role='E')

class PersonManager(models.Manager):
def get_queryset(self):
return PersonQuerySet(self.model, using=self._db)

def authors(self):
return self.get_queryset().authors()

def editors(self):
return self.get_queryset().editors()

class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
role = models.CharField(max_length=1, choices=(('A', _('Author')), ('E', _('Editor'))))
people = PersonManager()

Este exemplo permite chamar os dois authors()e editors()diretamente do gerenciador Person.people.

Criando um gerente com QuerySetmétodos


Em vez da abordagem acima, que requer métodos de duplicação no QuerySete no Manager, QuerySet.as_manager()pode ser usado para criar uma instância Managercom uma
cópia dos QuerySetmétodos de um custom :

class Person(models.Model):
...
people = PersonQuerySet.as_manager()

A Managerinstância criada por QuerySet.as_manager()será virtualmente idêntica à do PersonManagerexemplo anterior.

Nem todo QuerySetmétodo faz sentido no Managernível; por exemplo, intencionalmente evitamos que o QuerySet.delete()método seja copiado para a Managerclasse.

Os métodos são copiados de acordo com as seguintes regras:

Métodos públicos são copiados por padrão.

Métodos privados (começando com um sublinhado) não são copiados por padrão.

Métodos com um queryset_onlyatributo de nido como Falsesempre são copiados.

Métodos com um queryset_onlyatributo de nido como Truenunca são copiados.

Por exemplo:

Idioma: en

Versão da documentação: 2.1


class CustomQuerySet(models.QuerySet):
# Available on both Manager and QuerySet.
def public_method(self):
return

# Available only on QuerySet.


def _private_method(self):
return

# Available only on QuerySet.


def opted_out_public_method(self):
return
opted_out_public_method.queryset_only = True

# Available on both Manager and QuerySet.


def _opted_in_private_method(self):
return
_opted_in_private_method.queryset_only = False

from_queryset()

classmethodfrom_queryset ( queryset_class )

Para uso avançado, você pode querer um personalizado Managere um personalizado QuerySet. Você pode fazer isso chamando o Manager.from_queryset()que retorna uma
subclasse de sua base Managercom uma cópia dos QuerySetmétodos customizados :

class BaseManager(models.Manager):
def manager_only_method(self):
return

class CustomQuerySet(models.QuerySet):
def manager_and_queryset_method(self):
return

class MyModel(models.Model):
objects = BaseManager.from_queryset(CustomQuerySet)()

Você também pode armazenar a classe gerada em uma variável:

CustomManager = BaseManager.from_queryset(CustomQuerySet)

class MyModel(models.Model):
objects = CustomManager()

Gerenciadores customizados e herança de modelos


Veja como o Django lida com gerentes personalizados e herança de modelos :

1. Os gerentes das classes base são sempre herdados pela classe lha, usando a ordem normal de resolução de nomes do Python (os nomes na classe lha substituem todos os
outros; depois, os nomes na primeira classe pai, e assim por diante).

2. Se nenhum gerenciador for declarado em um modelo e / ou seus pais, o Django cria automaticamente o objectsgerenciador.

3. O gerenciador padrão em uma classe é o escolhido com Meta.default_manager_name, ou o primeiro gerenciador declarado no modelo, ou o gerenciador padrão do
primeiro modelo pai.

Essas regras fornecem a exibilidade necessária se você deseja instalar uma coleção de gerenciadores customizados em um grupo de modelos, por meio de uma classe base abstrata,
mas ainda customizar o gerenciador padrão. Por exemplo, suponha que você tenha essa classe base:

Idioma: en

Versão da documentação: 2.1


class AbstractBase(models.Model):
# ...
objects = CustomManager()

class Meta:
abstract = True

Se você usar isso diretamente em uma subclasse, objectsserá o gerente padrão se você não declarar nenhum gerenciador na classe base:

class ChildA(AbstractBase):
# ...
# This class has CustomManager as the default manager.
pass

Se você quiser herdar AbstractBase, mas fornecer um gerenciador padrão diferente, forneça o gerenciador padrão na classe lha:

class ChildB(AbstractBase):
# ...
# An explicit default manager.
default_manager = OtherManager()

Aqui default_managerestá o padrão. O objectsgerente ainda está disponível, já que é herdado. Apenas não é usado como padrão.

Finalmente, para este exemplo, suponha que você queira adicionar gerentes extras à classe lha, mas ainda usar o padrão de AbstractBase. Você não pode adicionar o novo
gerenciador diretamente na classe lha, pois isso substituiria o padrão e você também teria que incluir explicitamente todos os gerentes da classe base abstrata. A solução é colocar os
gerentes extras em outra classe base e introduzi-la na hierarquia de herança após os padrões:

class ExtraManager(models.Model):
extra_manager = OtherManager()

class Meta:
abstract = True

class ChildC(AbstractBase, ExtraManager):


# ...
# Default manager is CustomManager, but OtherManager is
# also available via the "extra_manager" attribute.
pass

Observe que, embora você possa de nir um gerenciador customizado no modelo abstrato, não é possível invocar nenhum método usando o modelo abstrato. Isso é:

ClassA.objects.do_something()

é legal, mas:

AbstractBase.objects.do_something()

irá levantar uma exceção. Isso ocorre porque os gerentes são destinados a encapsular a lógica para gerenciar coleções de objetos. Como você não pode ter uma coleção de objetos
abstratos, não faz sentido gerenciá-los. Se você tem uma funcionalidade que se aplica ao modelo abstrato, você deve colocar essa funcionalidade em um staticmethodou
classmethodno modelo abstrato.

Idioma: en

Questões de implementação Versão da documentação: 2.1


Quaisquer que sejam os recursos adicionados ao seu personalizado Manager, deve ser possível fazer uma cópia super cial de uma Managerinstância; ou seja, o seguinte código deve
funcionar:

>>> import copy


>>> manager = MyManager()
>>> my_copy = copy.copy(manager)

O Django faz cópias rasas de objetos gerenciadores durante certas consultas; Se o seu gerente não puder ser copiado, essas consultas falharão.

Isso não será um problema para a maioria dos gerentes personalizados. Se você está apenas adicionando métodos simples ao seu Manager, é improvável que você faça
inadvertidamente instâncias do seu não Managercopiável. No entanto, se você estiver substituindo __getattr__ou algum outro método particular do seu Managerobjeto que controla
o estado do objeto, certi que-se de não afetar a capacidade de Managerser copiado.

 Procurar Executando consultas SQL brutas 

Saber mais

Sobre o Django

Começando com o Django

Organização da equipe

Fundação de Software Django

Código de conduta

Declaração de diversidade

Se envolver

Junte-se a um grupo

Contribua para o Django

Envie um bug

Relatar um problema de segurança

Siga-nos

GitHub

Twitter

Notícias RSS
Idioma: en

Lista de discussão de usuários do Django


Versão da documentação: 2.1
© 2005-2019 Django Software Foundation e colaboradores individuais. Django é uma marca registrada da Django Software Foundation.

Idioma: en

Versão da documentação: 2.1

Vous aimerez peut-être aussi