Académique Documents
Professionnel Documents
Culture Documents
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:
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 .
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
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.
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
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:
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.
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
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.
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()
class Person(models.Model):
...
people = PersonQuerySet.as_manager()
Nem todo QuerySetmétodo faz sentido no Managernível; por exemplo, intencionalmente evitamos que o QuerySet.delete()método seja copiado para a Managerclasse.
Métodos privados (começando com um sublinhado) não são copiados por padrão.
Por exemplo:
Idioma: en
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)()
CustomManager = BaseManager.from_queryset(CustomQuerySet)
class MyModel(models.Model):
objects = CustomManager()
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
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
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
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.
Saber mais
Sobre o Django
Organização da equipe
Código de conduta
Declaração de diversidade
Se envolver
Junte-se a um grupo
Envie um bug
Siga-nos
GitHub
Notícias RSS
Idioma: en
Idioma: en