Django 3.0
发布了,此版本带来了一些新特性,其中最值得关注的应当是其开始支持异步功能。

  一、Django: Python Web应用开发框架

add by zhj:
本文作者是DabApps公司的技术主管,作者认为在view中直接使用Django提供的ORM查询方法是不好的,我对此并不赞同,可能作者

此前我们报导过,有草案提出要让 Django 支持异步。聚集于 HTTP 中间件视图和
ORM,开发者要在 Django 中添加异步支持,同时维护对同步 Python
的支持,并且将完全向后兼容。

 

写这篇文章是给Django的初学者看,所以在说明方法演进时有些罗嗦,至少方法1是没有必要说的。

该设想最终会替换掉 Django 中的大多数阻塞部分,包括 Session、Auth、ORM 与
Handlers 等,使其原生支持异步。而同步 API
将继续存在并得到完全支持,其中一些最终将转变为原生异步代码的同步包装器。

    Django是一个开放源代码的Web应用框架,由Python写成。采用了MVC的软件设计模式,即模型M,视图V和控制器C。它最初是被开发来用于管理劳伦斯出版集团旗下的一些以新闻内容为主的网站的,

本文介绍了如何给QuerySet类增加方法属性。作者写本文时,Django1.7还在开发中,没有发布。在Django1.7版本中提供了这个功能,

ASGI 模式将 Django 作为原生异步应用程序运行,原有的 WSGI 模式将围绕每个
Django 调用运行单个事件循环,以使异步处理层与同步服务器兼容。

  即是CMS(内容管理系统)软件。并于2005年7月在BSD许可证下发布。这套框架是以比利时的吉普赛爵士吉他手Django
Reinhardt来命名的。

见。另:我对译文有修改。

在这个改造的过程中,每个特性都会经历以下三个实现阶段:

           Django
应该是最出名的Python框架,GAE甚至Erlang都有框架受它影响。Django是走大而全的方向,它最出名的是其全自动化的管理后台:只需要使用起ORM,做简单的对象定义,它就能自动生成数据库结构、以及全功能的管理后台。

英文原文:

  • Sync-only,只支持同步,也就是当前的情况
  • Sync-native,原生同步,同时带有异步封装器
  • Async-native,原生异步,同时带同步封装器

         
 Django提供的方便,也意味着Django内置的ORM跟框架内的其他模块耦合程度高。应用程序必须使用Django内置的ORM,否则就不能享受到框架内提供的种种基于其ORM的便利;理论上可以切换掉其ORM模块,

译文原文:

Django 3.0 开始提供运行 ASGI 应用支持,让 Django
逐渐具备异步功能。做了这一改动后,Django
现在会感知到异步事件循环,并将阻止从异步上下文调用标记为“异步不安全”的代码(例如
ORM 操作),如果开发者之前使用的是异步代码,则可能会触发。如果看到
SynchronousOnlyOperation
错误,可以仔细检查代码并将数据库操作移到同步子线程中。

  但这就相当于要把装修完毕的房子拆除重新装修,倒不如一开始就去毛胚房做全新的装修。Django的卖点是超高的开发效率,其性能扩展有限;采用Django的项目,在流量达到一定规模后,都需要对其进行重构,才能满足性能的要求。

译者:Naixjs,
fkkeee,
晴风晓月

其它方面,Django 现在支持 MariaDB 10.1 及更高版本;新的
ExclusionConstraint 类可以在 PostgreSQL 上添加排除约束;输出
BooleanField 的表达式现在可以直接在 QuerySet
过滤器中使用,而无需先注解然后对注解进行过滤;自定义枚举类型
TextChoices、IntegerChoices 和 Choices 现在可用作定义 Field.choices
的方法。

 

摘要

此外还有一些小改动,详情查看更新说明:

  二、Diesel:基于Greenlet的事件I/O框架

在这篇文章里,我认为在view中直接使用Django的低级的ORM查询方法(如filter,
order_by等)通常是反模式的。作为一种替代方式,我们需要在模型层建立

  • https://docs.djangoproject.com/en/dev/releases/3.0

 

查询API,这在Django中做起来不是非常容易,但通过深入地了解ORM的内部,我将告诉你一些简捷的方式来达到这个目的。

需要注意的是,Django 3.0 支持 Python 3.6、3.7 与 3.8,Django 2.2.x
系列是最后一个支持 Python 3.5 的系列。官方同时也建议第三方应用作者放弃对
Django 2.2 之前的所有版本的支持。

    Diesel提供一个整洁的API来编写网络客户端和服务器。支持TCP和UDP。

 

(文/开源中国)    

    你应该使用diesel来编写你的下一个网络应用。得益于Python使得diesel语法非常整洁,发展步伐非常迅速。非阻塞I/O使得diesel非常快速并且容易扩展。greenlets使得diesel有了unwind(to(callbacks(no)))。

概览

    nose使得测试变得容易。最后,Flask使得你不需要写一个新的网络框架来使用diesel。

当编写Django应用程序时,我们已经习惯通过添加method到model中以此达到封装业务逻辑并隐藏实现细节。这种方法看起来是非常的自然,而且实际上它也用在

  示例

    图片 1

                           需要框架项目实战视频  +  Python学习交流
  643692991   

  三、Flask:一个用Python编写的轻量级Web应用框架

 

    Flask是一个使用Python编写的轻量级Web应用框架。基于Werkzeug
WSGI工具箱和Jinja2 模板引擎。 Flask使用BSD授权。
Flask也被称为“microframework”,因为它使用简单的核心,用extension增加其他功能。

  Flask没有默认使用的数据库、窗体验证工具。然而,Flask保留了扩增的弹性,可以用Flask-extension加入这些功能:ORM、窗体验证工具、文件上传、各种开放式身份验证技术。

Django的内建应用中。

 

from django.contrib.auth.models import User
user = User.objects.get(pk=5)
user.set_password('super-sekrit')
user.save()

  Flask 很有趣

 

    图片 2

这里的set_password就是一个定义在django.contrib.auth.models.User这个model中的方法,它隐藏了对密码进行哈希操作的具体实现。相应的代码看起来应该

    配置简单

    图片 3

是这样:

  特性

    1、内置开发用服务器和debugger

    2、集成单元测试(unit testing)

    3、RESTful request dispatching

    4、使用Jinja2模板引擎

    5、支持secure cookies(client side sessions)

    6、100% WSGI 1.0兼容

    7、Unicode based

    8、详细的文件、教学

    9、Google App Engine兼容

    10、可用Extensions增加其他功能

 

  四、Cubes:轻量级Python OLAP框架

    Cubes是一个轻量级Python框架,包含OLAP、多维数据分析和浏览聚合数据(aggregated
data)等工具

    Cubes的主要特性之一是它的逻辑模型,抽象物理数据并提供给终端用户层。

    图片 4

                              需要框架项目实战视频  +  Python学习交流
  643692991  

 

  五、Kartograph.py:创造矢量地图的轻量级Python框架

 

    Kartograph是一个Python库,用来为ESRI生成SVG地图。Kartograph.py目前仍处于beta阶段,你可以在virtualenv环境下来测试。

    图片 5

图片 6

  六、Pulsar:Python的事件驱动并发框架

 

    Pulsar是一个事件驱动的并发框架,有了pulsar,你可以写出在不同进程或线程中运行一个或多个活动的异步服务器。

from django.contrib.auth.hashers import make_password

class User(models.Model):

    # fields go here..

    def set_password(self, raw_password):
        self.password = make_password(raw_password)

  应用

    附带以下功能

    1、Socket服务器

    2、WSGI服务器

    3、JSON-RPC

    4、Web Sockets

    5、任务队列

    6、Shell

    7、测试包

    8、django集成

这样做的好处是使代码更具可读性、重用性和健壮性。

  示例

    对所有请求都返回“Hello World!”作为响应

 

    图片 7

                       需要框架项目实战视频  +  Python学习交流
  643692991  

  七、Web2py:全栈式Web框架

 

    Web2py是一个为Python语言提供的全功能Web应用框架,旨在敏捷快速的开发Web应用,具有快速、安全以及可移植的数据库驱动的应用,兼容Google
App Engine。

我们已经在单独的例子中这样做了,下面将会把它用在获取数据库信息的例子中。

  Web2py目录结构

 

    图片 8

 

  八、Falcon:构建云API和网络应用后端的高性能Python框架

       

    Falcon是一个构建云API的高性能Python框架,它鼓励使用REST架构风格,尽可能以最少的力气做最多的事情。

为了描述这个方法,我们使用了一个简单的app(todo
list)来说明。注意:这是一个例子,因为很难用少量的代码展示一个真实的例子。

  特性

    1、通过URI模板和资源类的路由

    2、通过请求和响应类访问headers和bodies

    3、通过异常基类响应HTTP错误等等

下面就是models.py文件:

  基准测试

    图片 9

    图片 10

 

    图片 11
                           需要框架项目实战视频  +  Python学习交流
  643692991  

  九、Dpark:Python版的Spark

 

    图片 12

    DPark是一个基于Mesos的集群计算框架(cluster computing
framework),是Spark的Python实现版本,类似于MapReduce,但是比其更灵活,可以用Python非常方便地进行分布式计算,并且提供了更多的功能以便更好

  的进行迭代式计算。DPark的计算模型是基于两个中心思想的:对分布式数据集的并行计算以及一些有限的可以在计算过程中、从不同机器访问的共享变量类型。这个的目标是为了提供一种类似于global
address space

   programming
model的工具,例如OpenMP,但是我们要求共享变量的类型必须是那些很容易在分布式系统当中实现的,当前支持的共享变量类型有只读的数据和支持一种数据修改方式的累加器(accumulators)。

  DPark具有的一个很重要的特性:分布式的数据集可以在多个不同的并行循环当中被重复利用。这个特性将其与其他数据流形式的框架例如Hadoop和Dryad区分开来。

from django.db import models

PRIORITY_CHOICES = [(1, 'High'), (2, 'Low')]

class Todo(models.Model):
    content = models.CharField(max_length=100)
    is_done = models.BooleanField(default=False)
    owner = models.ForeignKey('auth.User')
    priority = models.IntegerField(choices=PRIORITY_CHOICES, default=1

  示例

    一个word counting程序

 

    图片 13

    上面的脚本可以无修改的在Mesos集群上运行,只需稍微修改一下命令行参数:

    图片 14


  十、Buildbot:基于Python的持续集成测试框架

 

    Buildbot是一个开源框架,可以自动化软件构建、测试和发布等过程。每当代码有改变,服务器要求不同平台上的客户端立即进行代码构建和测试,收集并报告不同平台的构建和测试结果。

 

    图片 15

                            需要框架项目实战视频  +  Python学习交流
  643692991  

  十一、Zerorpc:基于ZeroMQ的高性能分布式RPC框架

 

    Zerorpc是一个基于ZeroMQ和MessagePack开发的远程过程调用协议(RPC)实现。和 Zerorpc
一起使用的 Service API 被称为 zeroservice。Zerorpc
可以通过编程或命令行方式调用。

    它允许你:

    1、不用修改代码即可显露python模块

    2、通过命令行远程调用这些模块

    如何把你代码中的对象暴露为一个zeroservice?

 

    图片 16

    运行以上代码,在另一个终端,尝试连接这个zeroservice

    图片 17

  十二、Bottle: 微型Python Web框架

 

    Bottle是一个简单高效的遵循WSGI的微型python
Web框架。说微型,是因为它只有一个文件,除Python标准库外,它不依赖于任何第三方模块。

想像一下,我们需要查询当前用户所有不完整的,高优先级的
Todos。这里是代码:

  特性

    1、Routing:把请求映射到函数,建立简洁动态的URLs

    2、Templates:采用内置模板引擎,同时还支持 mako, jinja2, cheetah
等第三方模板

    3、Utilities:便捷地读取表单数据、上传文件、
cookies、HTTP头信息和其它 HTTP相关的元数据

    4、Server:内置HTTP开发服务器,并且支持 paste, fapws3, bjoern,
Google App Engine, Cherrypy 或者其它任何WSGI HTTP 服务器

 

def dashboard(request):

    todos = Todo.objects.filter(
        owner=request.user
    ).filter(
        is_done=False
    ).filter(
        priority=1
    )

    return render(request, 'todos/list.html', {
        'todos': todos,
    })

  示例

    图片 18

    运行上面的代码,访问

注意:这里可以写成request.user.todo_set.filter(is_done=False,
priority=1)。但是记住这里只是一个实验。

  下载和安装

    通过

    图片 19

    或者

    图片 20

    安装最新稳定版,或者下载bottle.py
(不稳定)到你的工程目录。Bottle运行于Python 2.5+ and 3.x环境下。

              需要框架项目实战视频  +  Python学习交流   643692991  

  十三、Tornado:异步非阻塞IO的Python Web框架

 

    Tornado的全称是Torado Web
Server,从名字上看就可知道它可以用作Web服务器,但同时它也是一个Python
Web的开发框架。最初是在FriendFeed公司的网站上使用,FaceBook收购了之后便开源了出来。

    作为Web框架,是一个轻量级的Web框架,类似于另一个Python web
框架Web.py,其拥有异步非阻塞IO的处理方式。

    作为Web服务器,Tornado有较为出色的抗负载能力,官方用nginx反向代理的方式部署Tornado和其它Python
web应用框架进行对比,结果最大浏览量超过第二名近40%。

    此外,它的源代码也是Python开发者学习与研究的绝佳材料。

    以下是Tornado的Hello World示例程序。

 

    图片 21

  十四、webpy: 轻量级的Python Web框架

 

    webpy的设计理念力求精简(Keep it simple and
powerful),源码很简短,只提供一个框架所必须的东西,不依赖大量的第三方模块,它没有URL路由、没有模板也没有数据库的访问。这样的优点是,

  框架给开发带来的限制少,可以根据自己的需求进行定制。缺点就是,很多东西都需要自己亲自动手开发。

             虽然webpy的作者Aaron
H.Swartz,一位伟大的程序员在2013年1月11日自杀身亡,结束了短暂的26年生命。但是,作为一个开源项目,目前还是有很多开发者在持续更新。

    webpy非常的简单,语法几乎跟Python一样,以下是一个简单的示例:

 

    图片 22

                                    需要框架项目实战视频  +
 Python学习交流   643692991  

  十五、Scrapy:Python的爬虫框架

 

           
 网络爬虫,是在网上进行数据抓取的程序,使用它能够抓取特定网页的HTML数据。虽然我们利用一些库开发一个爬虫程序,但是使用框架可以大大提高效率,缩短开发时间。Scrapy是一个使用Python编写的,

  轻量级的,简单轻巧,并且使用起来非常的方便。

  Scrapy使用了Twisted异步网络库来处理网络通讯。整体架构大致如下(注:图片来自互联网):

 

    图片 23

    Scrapy主要包括了以下组件:

    1、引擎,用来处理整个系统的数据流处理,触发事务。

    2、调度器,用来接受引擎发过来的请求,压入队列中,并在引擎再次请求的时候返回。

    3、下载器,用于下载网页内容,并将网页内容返回给蜘蛛。

    4、蜘蛛,蜘蛛是主要干活的,用它来制订特定域名或网页的解析规则。

    5、项目管道,负责处理有蜘蛛从网页中抽取的项目,他的主要任务是清晰、验证和存储数据。当页面被蜘蛛解析后,将被发送到项目管道,并经过几个特定的次序处理数据。

    6、下载器中间件,位于Scrapy引擎和下载器之间的钩子框架,主要是处理Scrapy引擎与下载器之间的请求及响应。

    7、蜘蛛中间件,介于Scrapy引擎和蜘蛛之间的钩子框架,主要工作是处理蜘蛛的响应输入和请求输出。

    8、调度中间件,介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。

    使用Scrapy可以很方便的完成网上数据的采集工作,它为我们完成了大量的工作,而不需要自己费大力气去开发。

为什么这样写不好呢?

首先,代码冗长。七行代码才能完成,正式的项目中,将会更加复杂。

其次,泄露实现细节。比如我们需要知道model中有一个名为is_done的布尔型字段,如果你将字段类型修改为有多个允许值的field,那这个代码就不能用了。

然后就是,意图不清晰,很难理解。

最后,使用中会有重复。例:你需要写一个management
command,每周给每个用户发送他自己的todo
list,这时候你就需要复制-粘贴着七行代码。这不符合

DRY(do not repeat yourself)

让我们总结一下:直接使用低等级的ORM代码是反模式的。

如何改进呢?

使用 Managers 和 QuerySets

首先,让我们先了解一下概念。

Django 有两个关系密切的与表级别操作相关的结构:managers 和 querysets

manager(django.db.models.manager.Manager的一个实例)被描述成
“为model提供查询数据库操作的接口”。Manager是通往表级功能的大门。每一个model

都有一个默认的manager,叫做objects。

Quesyset (django.db.models.query.QuerySet)
是“数据库中objects的集合”。本质上是一个lazy
SELECT查询,也可以使用过滤,排序等(filtered,ordered),

来限制或者修改查询 到的数据。用它来创建或操纵
django.db.models.sql.query.Query实例,然后在数据库后台转换成SQL查询。

啊?你还不明白?

随着你慢慢深入的了解ORM,你就会明白Manager和QuerySet之间的区别了。

人们会被所熟知的Manager接口搞糊涂,因为他并不是看上去那样。

Manager接口就是个谎言。

QuerySet方法是可链式调用的。每一次调用QuerySet的方法(如:filter)都会返回一个复制的queryset等待下一次的调用。这也是Django
ORM 流畅之美的一部分。

QuerySet
的所有方法需要在Manager中要重新实现,从而通过model.objects也可以实现链式调用。这些方法在Manager中只是QuerySet中对应方法的代理,通过

self.get_query_set(),如下

class Manager(object):

    # SNIP some housekeeping stuff..

    def get_query_set(self):
        return QuerySet(self.model, using=self._db)

    def all(self):
        return self.get_query_set()

    def count(self):
        return self.get_query_set().count()

    def filter(self, *args, **kwargs):
        return self.get_query_set().filter(*args, **kwargs)

    # and so on for 100+ lines...

 

让我们立刻回到todo list
,解决query接口的问题。Django推荐的方法是自定义Manager子类,并加在models中。

class IncompleteTodoManager(models.Manager):
    def get_query_set(self):
        return super(TodoManager, self).get_query_set().filter(is_done=False)

class HighPriorityTodoManager(models.Manager):
    def get_query_set(self):
        return super(TodoManager, self).get_query_set().filter(priority=1)

class Todo(models.Model):
    content = models.CharField(max_length=100)
    # other fields go here..

    objects = models.Manager() # the default manager

    # attach our custom managers:
    incomplete = models.IncompleteTodoManager()
    high_priority = models.HighPriorityTodoManager()

你也可以在model中增加多个managers,或者重新定义objects,也可以维持单个的manager,增加自定义方法。

下面让我们实验一下这几种方法:

 

方法1:多managers

class IncompleteTodoManager(models.Manager):
    def get_query_set(self):
        return super(TodoManager, self).get_query_set().filter(is_done=False)

class HighPriorityTodoManager(models.Manager):
    def get_query_set(self):
        return super(TodoManager, self).get_query_set().filter(priority=1)

class Todo(models.Model):
    content = models.CharField(max_length=100)
    # other fields go here..

    objects = models.Manager() # the default manager

    # attach our custom managers:
    incomplete = models.IncompleteTodoManager()
    high_priority = models.HighPriorityTodoManager()

我们的API看起来是这样:

>>> Todo.incomplete.all()
>>> Todo.high_priority.all()

这个方法有几个问题。

第一,这种实现方式比较啰嗦。你要为每一个自定义查询定义一个manager。

第二,这将会弄乱你的命名空间。因为Django开发者习惯把Model.objects看做表的入口,而这种方法会破坏这个规则。


三,不可链式调用。还是要用低等级的ORM代码实现:Todo.incomplete.filter(priority=1)
或Todo.high_priority.filter(is_done=False)

综上,使用多managers的方法,不是最优选择。

 

方法2: Manager 方法

现在,我们试下其他Django允许的方法:在单个自定义Manager中的多个方法

class TodoManager(models.Manager):
    def incomplete(self):
        return self.filter(is_done=False)

    def high_priority(self):
        return self.filter(priority=1)

class Todo(models.Model):
    content = models.CharField(max_length=100)
    # other fields go here..

    objects = TodoManager()

我们的API 现在看起来是这样:

>>> Todo.objects.incomplete()
>>> Todo.objects.high_priority()

这个方法显然更好。它没有太多累赘(只有一个Manager类)并且可以很方便地添加更多的方法。

不过仍然不能链式调用自定义方法,因为Todo.objects.incomplete()
和Todo.objects.high_priority()返回的都是Django
QuerySet类的实例,所以我们

无法使用Todo.objects.incomplete().high_priority() 。

 

方法3:自定义QuerySet

现在我们已进入Django尚未开发的领域,Django文档中找不到这些内容。

class TodoQuerySet(models.query.QuerySet):
    def incomplete(self):
        return self.filter(is_done=False)

    def high_priority(self):
        return self.filter(priority=1)

class TodoManager(models.Manager):
    def get_query_set(self):
        return TodoQuerySet(self.model, using=self._db)

class Todo(models.Model):
    content = models.CharField(max_length=100)
    # other fields go here..

    objects = TodoManager()

我们从以下调用的视图代码中可以看出端倪:

>>> Todo.objects.get_query_set().incomplete()
>>> Todo.objects.get_query_set().high_priority()
>>> # (or)
>>> Todo.objects.all().incomplete()
>>> Todo.objects.all().high_priority()

差不多完成了!这并有比第2个方法多多少累赘,得到方法2同样的好处,和额外的效果(来点鼓声吧…),它终于可链式查询了!

>>> Todo.objects.all().incomplete().high_priority()

然而它还不够完美。这个自定义的Manager仅仅是一个样板而已,而且 all()
还有瑕疵,在使用时不好把握,而更重要的是不兼容,它让我们的代码看起来有点怪异。

 

方法3a:复制Django,代理做所有事

我们简单地在Manager中重新定义所有QuerySet方法

QuerySet:

class TodoQuerySet(models.query.QuerySet):
    def incomplete(self):
        return self.filter(is_done=False)

    def high_priority(self):
        return self.filter(priority=1)

class TodoManager(models.Manager):
    def get_query_set(self):
        return TodoQuerySet(self.model, using=self._db)

    def incomplete(self):
        return self.get_query_set().incomplete()

    def high_priority(self):
        return self.get_query_set().high_priority()

这个能更好地提供我们想要的API:

>>> Todo.objects.incomplete().high_priority() # yay!

但代码冗余、且不符合DRY,每次你新增一个文件到QuerySet,或是更改现有的方法标记,你必须记住在你的Manager中做相同的更改,否则它可能不会正常工作。

 

方法3b: django-model-utils

Python
是一种动态语言,我们可以做到DRY吗?答案是肯定的,要通过一个名叫Django-model-utils的第三方应用帮忙。运行
pip install django-model-utils ,

然后……

from model_utils.managers import PassThroughManager

class TodoQuerySet(models.query.QuerySet):
    def incomplete(self):
        return self.filter(is_done=False)

    def high_priority(self):
        return self.filter(priority=1)

class Todo(models.Model):
    content = models.CharField(max_length=100)
    # other fields go here..

    objects = PassThroughManager.for_queryset_class(TodoQuerySet)()

这要好多了。我们只是定义QuerySet子类,然后通过django-model-utils提供的PassThroughManager类附加这个自定义QuerySet子类到我们的model中。

PassThroughManager 是由__getattr__
实现的,当调用objects不存在的方法时,它会自动代理它们到QuerySet。这里需要小心一点,检查确认我们没有在一

些特性中没有无限递归(这是我为什么推荐使用django-model-utils,而不是自己手工写)。

做这些有什么帮助?

记得之前定义的view吗?

def dashboard(request):

    todos = Todo.objects.filter(
        owner=request.user
    ).filter(
        is_done=False
    ).filter(
        priority=1
    )

    return render(request, 'todos/list.html', {
        'todos': todos,
    })

加点小改动,它看起来是这样:

def dashboard(request):

    todos = Todo.objects.for_user(
        request.user
    ).incomplete().high_priority()

    return render(request, 'todos/list.html', {
        'todos': todos,
    })

希望你也能同意第二个版本比第一个更简便,清晰并且更有可读性。

Django能帮忙么?

让这整个事情更容易的方法,已经在django开发邮件列表中讨论过,下面是Zachary
Voase的建议:

class TodoManager(models.Manager):

    @models.querymethod
    def incomplete(query):
        return query.filter(is_done=False)

通过这个简单的装饰方法的定义,让Manager和QuerySet都能使不可用的方法神奇地变为可用。

我个人并不完全赞同使用装饰器的方法。它略过了详细的信息,感觉有点“嘻哈”。我感觉好的方法是增加一个QuerSet子类(而不是Manager子类)。

或者我们更进一步思考。退回到在争议中重新审视Django的API设计决定时,也许我们能得到真实更深的改进。可以消除Managers和QuerySet的区别吗

(或者至少使这个区别更明显)?

我很确信,不管以前是否曾经有过这么大的重构工作,这个功能必然要在Django
2.0 甚至更后的版本中。

因此,简单概括一下:

在视图和其他高级应用中使用源生的ORM查询代码不是很好的主意。而是用django-model-utils中的PassThroughManager将我们新加的自定义QuerySet
API

加进你的模型中,这能给你以下好处:

   啰嗦代码少,并且更健壮。

   增加DRY,增强抽象级别。

  将所属的业务逻辑推送至模型层实现。

感谢阅读。