【发布时间】:2013-06-03 17:11:01
【问题描述】:
由于我正在处理的项目中存在一些限制,我不得不将 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 团队会这样做。
【问题讨论】:
-
返回一个克隆的对象意味着原始对象是保证不变的(你正在更改克隆,而不是原始对象)。不过,这只是我的一个观察。
-
@RobertHarvey - 看起来很有效,看看这里的解释:docs.djangoproject.com/en/1.0/ref/models/querysets/#all
-
我正在查看该文件的
git blame输出,我看到self._clone()来自多个提交。不管是什么原因,这种设计已经持续实施了一段时间。 github.com/django/django/blame/master/django/db/models/query.py -
+1 非常有趣的问题。
-
@AdriánLópez,不幸的是没有。由于架构要求,我们必须将数据库移到“墙”后面,并通过 TCP/IP 代理与其通信。因此,我们将发送请求,而不是查询。这超出了 Django 的范围。
标签: python django django-queryset