由于我正在进行的项目中存在一些限制,我不得不用自定义项替换Django的QuerySet类。
QuerySet对象可以将它们的方法链接起来(例如QuerySet().filter(...).exclude(...)
等等),因此在我的实现中,每个方法都只返回self
。所以我的班级看起来像这样:
class MyQuerySet:
...
def filter(self, *args, **kwargs):
# Do some stuff and then:
return self
这样我就模仿了Django的QuerySet行为。
然而,看着Django代码,我注意到,QuerySet的方法不是返回self
,而是在每次调用时返回克隆对象。它看起来像这样(删除了不必要的东西):
class QuerySet(...):
...
def filter(self, *args, **kwargs):
clone = self._clone()
# Do some stuff and then
return clone
def _clone(self,...):
klass = self.__class__
obj = klass(...)
return obj
所以基本上,每次调用一个方法时,QuerySet都会克隆自己,实例化一个新对象并返回它。
我的问题是:为什么?我的方式错了吗? 我担心的是我这样做的方式,有些东西可能会破裂,否则我无法解释为什么Django团队会做它所做的事情。
答案 0 :(得分:2)
Django执行此操作,以便可以保留基本查询并重复使用,而无需继承未来" child"查询,就像exclude()
上的filter()
一样。我猜测有人试图为以后存储查询,并意识到没有复制就没有用。
我克隆了django repo并在git log
上快速django/db/models/query.py
,搜索了短语clone
。
引入此更改的补丁如下: