什么是django的"经理"?

mas*_*ece 12 python django

我已经阅读了官方Django 文档中的定义,但我仍然对它的作用感到困惑Manager.

文档说它们允许您操作数据库表/模型.但我仍然不明白这一点.

有人可以向我解释经理及其角色吗?一个例子的答案将是更可取的.

dan*_*van 10

管理器通常是远离django程序员的东西,django用它来model代码和数据库后端之间的接口.

当您查询django ORM时,您可以通过调用来执行此操作

from my_app.models import MyModel

mms = MyModel.objects.all()
Run Code Online (Sandbox Code Playgroud)

在这种情况下,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()
Run Code Online (Sandbox Code Playgroud)

并打电话

MyModel.blue_objects.all()
Run Code Online (Sandbox Code Playgroud)

只返回带有colouras的对象blue.注意,这是一种非常差的过滤模型的方法!

Manager如果他们要修改QuerySet管理员通常返回的s或者如果你需要添加"表"级别查询(而不是常规的django"row"级别),通常需要修改接口.管理人员的文档非常完整,包含几个示例.


Luk*_*ara 6

管理器是应用程序和数据库之间的某种“门”。一件好事是,您可以为模型定义自己的基本查询集。例如:如果您有带有“可用性”字段的模型“书”,则可以准备自己的查询集,该查询集将过滤特定类型的可用性类型:

models.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
Run Code Online (Sandbox Code Playgroud)

现在您可以使用:

books = Book.available_objects.all()
Run Code Online (Sandbox Code Playgroud)

注意:

books = Book.objects.filter(available=1)
Run Code Online (Sandbox Code Playgroud)


lmi*_*asf 6

定义

从文档:

Manager 是一个 Django 类,它提供了数据库查询操作和 Django 模型之间的接口。

换句话说,在 Django 模型中,管理器是与数据库交互的接口。例如,当您想从数据库中检索对象时,您需要在模型类上构造一个QuerySetvia Manager

默认情况下,管理器可通过该Model.objects属性访问。这位经理是django.db.models.Manager. 但是,扩展它并更改默认管理器非常简单。

自定义管理器

文档

您可以通过扩展基本 Manager 类并在模型中实例化您的自定义 Manager,在特定模型中使用自定义 Manager。

您可能想要自定义管理器的原因有两个(它们都不是唯一的):

  1. 添加额外的管理器方法
  2. 修改管理器返回的初始 QuerySet

示例:向 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
Run Code Online (Sandbox Code Playgroud)

示例:修改 Manager 返回的初始 QuerySet

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}"
Run Code Online (Sandbox Code Playgroud)

示例:同时有多个经理

同一个模型可以有多个管理器。

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}'
Run Code Online (Sandbox Code Playgroud)

在前面的代码示例中,有3个管理器:缺省models.ManagerBookTitleManagerBookPagesManager分配给objectstitlessizes分别。

以前的管理器的问题是你不能将它们链接如下:

>>> Book.titles.long_titles().starts_with('P')
AttributeError: 'QuerySet' object has no attribute 'starts_with'
Run Code Online (Sandbox Code Playgroud)

示例:自定义管理器和查询集(允许链)

如果你想链接在管理器中定义的方法,你应该定义一个自定义的 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}"

Run Code Online (Sandbox Code Playgroud)

示例:用作管理器的自定义查询集

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

Run Code Online (Sandbox Code Playgroud)

还要记住

  • 如果要objects用作字段名称,或者要使用objectsManager以外的名称,可以按模型重命名。要为给定类重命名 Manager,请在该模型上定义一个 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

Run Code Online (Sandbox Code Playgroud)

在前面的代码示例中,调用Document.objects会产生AttributeError异常,因为默认管理器已重命名,现在可以使用的是Document.stuff.

  • 管理器只能通过模型​​类访问,而不是从模型实例访问,以强制分离“表级”操作和“记录级”操作。

  • 如果模型具有外键,则外键模型的实例将有权访问返回第一个模型的所有实例的管理器。默认情况下,此 Manager 名为FOO_set,其中FOO是小写的源模型名称。