Django小技巧11: 自定义链式Queryset Manager

翻译整理自: simpleisbetterthancomplex.com

在 Django Model 中,Manager是与数据库交互的接口。默认情况下Manager可通过Model.objects属性使用。默认情况下, 每个 Model 的默认 Manager 是django.db.models.Manager。扩展和重写默认Manager非常简单.

Python

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

设置后, 你可以通过pdfs方法快速的过滤属于 PDF 的文档.

Python

Document.objects.pdfs()

当然,返回的结果是链式的, 依然拥有 queryset 的一些操作方法(order_byfilter等..).

Python

Document.objects.pdfs().order_by('name')

但是, 如果你试图在使用自定义的一些方法, 链式将会中止:

Python

Document.objects.pdfs().smaller_than(1000)

AttributeError: 'QuerySet' object has no attribute 'smaller_than'

要使上述代码能够工作, 你必须创建自定义的get_queryset方法.

Python

class DocumentQuerySet(models.QuerySet):
    def pdfs(self):
        return self.filter(file_type='pdf')

    def smaller_than(self, size):
        return self.filter(size__lt=size)

class DocumentManager(models.Manager):
    def get_queryset(self):
        return DocumentQuerySet(self.model, using=self._db)  # Important!

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

    def smaller_than(self, size):
        return self.get_queryset().smaller_than(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()

现在可以像任何的 QuerySet 方法一样使用他。 并且是链式的!

Python

Document.objects.pdfs().smaller_than(1000).exclude(name='Article').order_by('name')

Manager 除了自定义 QuerySet 还可以做其他的工作, 如果你只在 Manager 中自定义 QuerySet ,推荐扩展下models.QuerySet, 并在模型中定义objects = DocumentQuerySet.as_manager().

Python

class DocumentQuerySet(models.QuerySet):
    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 = DocumentQuerySet.as_manager()

自定义的 Manager 代码, 你可以写在models.py, 但随着代码库的增长, 我更加推荐你将定义的QuerySetsManagers保存名为managers.py文件中.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏公众号_薛勤的博客

深入理解[Master-Worker模式]原理与技术

Master-Worker模式是常用的并行模式之一。它的核心思想是,系统由两类进程协作工作:Master进程和Worker进程。Master进程负责接收和分配任...

24950
来自专栏IMWeb前端团队

通过ffi在node.js中调用动态链接库(.so/.dll文件)

? 概述 为什么要在node.js中调用动态链接库 由于腾讯体系下的许多公共的后台服务(L5, CKV, msgQ等)已经有了非常成熟的C/C++编写的API...

60570
来自专栏Python

Django ORM详解

ORM:(在django中,根据代码中的类自动生成数据库的表也叫--code first) ORM:Object Relational Mapping(关系对象...

587100
来自专栏分布式系统进阶

Kafka集群Metadata管理Kafka源码分析-汇总

可以看到是调用了ReplicaManager.maybeUpdateMetadataCache方法, 里面又会调用到MetadataCache.updateCa...

28420
来自专栏JavaQ

源码阅读之CyclicBarrier

源码阅读是基于JDK7,本篇主要涉及CyclicBarrier常用方法源码分析。文中代码若格式排版不对,可点击底部的阅读原文阅读。 1.概述 CyclicBar...

34470
来自专栏Python攻城狮

Django模型(数据库)及Django Query常用方法

Django 模型是与数据库相关的,与数据库相关的代码一般写在 models.py 中,Django 支持 sqlite3, MySQL, PostgreSQL...

23940
来自专栏有趣的django

Django rest framework(6)----序列化

序列化 1.继承Serializer 基本使用  (1)models.py from django.db import models class UserI...

48490
来自专栏JackieZheng

RabbitMQ入门-Routing直连模式

Hello World模式,告诉我们如何一对一发送和接收消息; Work模式,告诉我们如何多管齐下高效的消费消息; Publish/Subscribe模式,告...

288100
来自专栏YG小书屋

ES维护常见问题(持续更新)

1.3K50
来自专栏Java3y

【不用框架】文件上传和下载

什么是文件上传? 文件上传就是把用户的信息保存起来。 为什么需要文件上传? 在用户注册的时候,可能需要用户提交照片。那么这张照片就应该要进行保存。 上传组件(工...

63940

扫码关注云+社区

领取腾讯云代金券