5

Due to some restrictions in a project I'm working on, I had to replace Django's QuerySet class with a custom one. QuerySet objects can have their methods chained (eg QuerySet().filter(...).exclude(...) and so on), so in my implementation, every method simply returns self. So my class looks like this:

class MyQuerySet:
    ...
    def filter(self, *args, **kwargs):
        # Do some stuff and then:
        return self

This way I imitated Django's QuerySet behaviour.

However, looking at the Django code, I noticed that instead of returning self, QuerySet's methods return a cloned object every time they are called. It looks like this (removed unnecessary stuff):

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

So basically, every time a method is called, QuerySet will clone itself, instantiate a new object and return it.

My question is: WHY? Is my way wrong?
My fear is that the way I do it, something might break, otherwise I can't explain why Django team did what it did.

4

1 回答 1

2

Django 这样做是为了保留和重用基本查询,而无需从未来的“子”查询继承更改,例如您exclude()filter(). 我猜有人试图为以后存储查询,并意识到如果不复制就不能很好地工作。

我克隆了 django repo 并快速搜索了该git log短语。django/db/models/query.pyclone

引入此更改的补丁在这里:

https://github.com/django/django/commit/d4a3a4b

于 2013-06-03T17:38:44.753 回答