我已经阅读了官方 Django文档中的定义,但我仍然对 a 的Manager
作用感到困惑。
文档说它们允许您对数据库表/模型进行操作,但我仍然不明白这一点。
有人可以向我解释经理及其角色吗?最好有一个例子的答案。
管理器通常是隐藏在 django 程序员之外的东西,django 使用它来连接model
代码和数据库后端。
当您查询 django ORM 时,您可以通过调用
from my_app.models import MyModel
mms = MyModel.objects.all()
在这种情况下,objects
函数的一部分是管理器返回的。如果您希望 MyModel 只获取blue
MyModel
实例(数据库也可能包含red
模型),那么您可以创建一个管理器并破解您的模型
class BlueManager(models.Manager):
def get_query_set(self):
return super(BlueManager, self).get_query_set().filter(colour='Blue')
class MyModel(models.Model):
colour = models.CharField(max_length=64)
blue_objects = BlueManager()
并打电话
MyModel.blue_objects.all()
只会返回带有colour
as 的对象blue
。请注意,这是过滤模型的一种非常糟糕的方法!
Manager
如果他们要修改QuerySet
管理器通常会返回的 s 或者如果您需要添加“表”级别的查询(而不是常规的 django “行”级别),通常需要修改接口。管理器的文档非常完整,包含几个示例。
管理器是应用程序和数据库之间的某种“门”。一件好事是您可以为模型定义自己的基本查询集。例如:如果您有带有“可用性”字段的模型“书”,您可以准备自己的查询集,它过滤特定类型的可用性类型:
模型.py:
class AvailableBookManager(models.Manager):
def get_query_set(self):
return super(AvailableBookManager, self).get_query_set().filter(availability=1)
class Book(models.Model):
(...)#fields definition
objects = models.Manager() #default manager
available_objects = AvailableBookManager() #own manager
现在你可以像这样使用:
books = Book.available_objects.all()
而不是使用:
books = Book.objects.filter(available=1)
从文档:
Manager 是一个 Django 类,它提供数据库查询操作和 Django 模型之间的接口。
换句话说,在 Django 模型中,管理器是与数据库交互的接口。例如,当您想从数据库中检索对象时,您需要在模型类上QuerySet
通过 a构造一个。Manager
默认情况下,可以通过该Model.objects
属性使用管理器。这位经理是django.db.models.Manager
。但是,扩展它并更改默认管理器非常简单。
从文档:
您可以通过扩展基础 Manager 类并在模型中实例化您的自定义 Manager 来在特定模型中使用自定义 Manager。
您可能想要自定义 Manager 的原因有两个(它们都不是独占的):
from django.db import models
class DocumentManager(models.Manager):
def pdfs(self):
return self.filter(file_type='pdf')
def smaller_than(self, size):
return self.filter(size__lt=size)
class Document(models.Model):
name = models.CharField(max_length=30)
size = models.PositiveIntegerField(default=0)
file_type = models.CharField(max_length=10, blank=True)
objects = DocumentManager()
def __str__(self) -> str:
return self.name
from django.db import models
class AuthorManager(models.Manager):
def get_queryset(self):
return super().get_queryset().filter(first_name__startswith='M')
class Author(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField()
objects = AuthorManager()
def __str__(self) -> str:
return f"{self.first_name} {self.last_name}"
同一模型可以有多个管理器。
from django.db import models
from django.db.models.functions import Length
class BookTitleManager(models.Manager):
def short_titles(self):
return self.annotate(length=Length('title')).filter(length__lte=20)
def long_titles(self):
return self.annotate(length=Length('title')).filter(length__gt=20, length__lte=30)
def very_long_titles(self):
return self.annotate(length=Length('title')).filter(length__gt=30)
def starts_with(self, letter):
return self.filter(title__startswith=letter)
class BookPagesManager(models.Manager):
def small_books(self):
return self.filter(pages__lt=200)
def medium_books(self):
return self.filter(pages__gte=200, pages__lt=300)
def large_books(self):
return self.filter(pages__gte=300, pages__lte=500)
class Book(models.Model):
title = models.CharField(max_length=255)
author = models.CharField(max_length=255)
pages = models.IntegerField()
objects = models.Manager()
titles = BookTitleManager()
sizes = BookPagesManager()
def __str__(self) -> str:
return f'{self.title} by {self.author}'
在前面的代码示例中,有 3 个管理器:分别为default和models.Manager
分配给BookTitleManager
和。BookPagesManager
objects
titles
sizes
以前的管理器的问题是您不能将它们链接如下:
>>> Book.titles.long_titles().starts_with('P')
AttributeError: 'QuerySet' object has no attribute 'starts_with'
如果要链接管理器中定义的方法,则应定义一个自定义 QuerySet,如下所示:
from django.db import models
from django.db.models.functions import Length
class AuthorQuerySet(models.QuerySet):
def long_first_name(self):
return self.annotate(length=Length("first_name")).filter(length__gte=10)
def short_last_name(self):
return self.annotate(length=Length("last_name")).filter(length__lte=10)
class AuthorManager(models.Manager):
def get_queryset(self):
return AuthorQuerySet(self.model, using=self._db)
def long_first_name(self):
return self.get_queryset().long_first_name()
def short_last_name(self):
return self.get_queryset().short_last_name()
class Author(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField()
objects = AuthorManager()
def __str__(self) -> str:
return f"{self.first_name} {self.last_name}"
在管理器中仅定义自定义QuerySets
时,可以简单地扩展并将其QuerySet
设置为管理器。
from django.db import models
from django.db.models.functions import Length
class PublisherQuerySet(models.QuerySet):
def long_name(self):
return self.annotate(length=Length("name")).filter(length__gte=15)
def long_address(self):
return self.annotate(length=Length("address")).filter(length__gte=25)
def country_starts_with(self, letter):
return self.filter(country__startswith=letter)
class Publisher(models.Model):
name = models.CharField(max_length=100)
address = models.CharField(max_length=255)
country = models.CharField(max_length=100)
objects = PublisherQuerySet.as_manager() # uses QuerySet as Manager
def __str__(self) -> str:
return self.name
objects
用作字段名称,或者要使用 Manager 以外的名称objects
,则可以按模型重命名。要重命名给定类的管理器,请在该模型上定义类型为 models.Manager() 的类属性。class Document(models.Model):
name = models.CharField(max_length=30)
size = models.PositiveIntegerField(default=0)
file_type = models.CharField(max_length=10, blank=True)
stuff = models.Manager()
def __str__(self) -> str:
return self.name
在前面的代码示例中,调用Document.objects
将生成AttributeError
异常,因为默认管理器已被重命名,现在可以使用的是Document.stuff
.
管理器只能通过模型类而不是模型实例来访问,以强制区分“表级”操作和“记录级”操作。
如果模型具有 ForeignKey,则外键模型的实例将有权访问返回第一个模型的所有实例的 Manager。默认情况下,此 Manager 名为FOO_set
,其中FOO
源模型名称为小写。