Revert commits about evaluating the queryset at the end.

This reverts commit a0a17c3630985fe960211708f5b90acf449f76b3.
This reverts commit 92122270e5815cbbf301a6e247c682a05717b19d.
This reverts commit c5d4c4d347e99be00258d55ec6338e3749084bbe.
This reverts commit c78876087d29511b6126132a213f4267249a869f.
This commit is contained in:
Laura Klünder 2017-06-16 11:47:40 +02:00
parent e187e1ef67
commit 9ba14677c0

View file

@ -1,6 +1,5 @@
import typing import typing
from collections import Iterable, deque from collections import deque
from functools import wraps
from itertools import chain from itertools import chain
from django.db import models from django.db import models
@ -10,8 +9,7 @@ from django.db.models.query_utils import DeferredAttribute
class BaseWrapper: class BaseWrapper:
_not_wrapped = ('_changeset', '_author', '_obj', '_commands', '_with_commands_executed', '_wrap_instances', _not_wrapped = ('_changeset', '_author', '_obj', '_changes_qs', '_initial_values', '_wrap_instances')
'_initial_values')
_allowed_callables = ('', ) _allowed_callables = ('', )
def __init__(self, changeset, obj, author=None): def __init__(self, changeset, obj, author=None):
@ -208,72 +206,47 @@ class ModelInstanceWrapper(BaseWrapper):
self._changeset.add_delete(self, author=author) self._changeset.add_delete(self, author=author)
def modifies_query(f): class ChangesQuerySet:
@wraps(f) def __init__(self, changeset, model, author):
def wrapper(self, *args, execute=False, **kwargs): self._changeset = changeset
if execute: self._model = model
return f(self, *args, **kwargs) self._author = author
if f.__name__ in ('filter', 'exclude'):
kwargs = {name: (tuple(value) if name.endswith('__in') and isinstance(value, Iterable) else value)
for name, value in kwargs.items()}
qs = self._wrap_queryset(self.get_queryset(), add_command=(f.__name__, args, kwargs))
qs.execute_commands()
return qs
return wrapper
def executes_query(f):
@wraps(f)
def wrapper(self, *args, **kwargs):
return f(self._with_commands_executed, *args, **kwargs)
return wrapper
class BaseQueryWrapper(BaseWrapper): class BaseQueryWrapper(BaseWrapper):
_allowed_callables = ('_add_hints', '_next_is_sticky', 'get_prefetch_queryset') _allowed_callables = ('_add_hints', '_next_is_sticky', 'get_prefetch_queryset')
def __init__(self, changeset, obj, author=None, commands=(), wrap_instances=True): def __init__(self, changeset, obj, author=None, changes_qs=None, wrap_instances=True):
super().__init__(changeset, obj, author) super().__init__(changeset, obj, author)
if changes_qs is None:
changes_qs = ChangesQuerySet(changeset, obj.model, author)
self._changes_qs = changes_qs
self._wrap_instances = wrap_instances self._wrap_instances = wrap_instances
self._commands = commands
self._with_commands_executed = self
def get_queryset(self): def get_queryset(self):
return self._obj return self._obj
def execute_commands(self):
result = self
for name, args, kwargs in self._commands:
result = getattr(result, name)(*args, execute=True, **kwargs)
result._commands = ()
self._with_commands_executed = result
def _wrap_instance(self, instance): def _wrap_instance(self, instance):
if self._wrap_instances: if self._wrap_instances:
return super()._wrap_instance(instance) return super()._wrap_instance(instance)
return instance return instance
def _wrap_queryset(self, queryset, add_command=None, wrap_instances=None): def _wrap_queryset(self, queryset, changes_qs=None, wrap_instances=None):
if changes_qs is None:
changes_qs = self._changes_qs
if wrap_instances is None: if wrap_instances is None:
wrap_instances = self._wrap_instances wrap_instances = self._wrap_instances
commands = self._commands return QuerySetWrapper(self._changeset, queryset, self._author, changes_qs, wrap_instances)
if add_command is not None:
commands += (add_command, )
return QuerySetWrapper(self._changeset, queryset, self._author, commands, wrap_instances)
@modifies_query
def all(self): def all(self):
return self._wrap_queryset(self.get_queryset().all()) return self._wrap_queryset(self.get_queryset().all())
@modifies_query
def none(self): def none(self):
return self._wrap_queryset(self.get_queryset().none()) return self._wrap_queryset(self.get_queryset().none())
@modifies_query
def select_related(self, *args, **kwargs): def select_related(self, *args, **kwargs):
return self._wrap_queryset(self.get_queryset().select_related(*args, **kwargs)) return self._wrap_queryset(self.get_queryset().select_related(*args, **kwargs))
@modifies_query
def prefetch_related(self, *lookups): def prefetch_related(self, *lookups):
new_lookups = deque() new_lookups = deque()
for lookup in lookups: for lookup in lookups:
@ -288,7 +261,6 @@ class BaseQueryWrapper(BaseWrapper):
new_lookups.append(Prefetch(lookup, qs)) new_lookups.append(Prefetch(lookup, qs))
return self._wrap_queryset(self.get_queryset().prefetch_related(*new_lookups)) return self._wrap_queryset(self.get_queryset().prefetch_related(*new_lookups))
@executes_query
def get(self, *args, **kwargs): def get(self, *args, **kwargs):
results = tuple(self.filter(*args, **kwargs)) results = tuple(self.filter(*args, **kwargs))
if len(results) == 1: if len(results) == 1:
@ -297,7 +269,6 @@ class BaseQueryWrapper(BaseWrapper):
raise self._obj.model.DoesNotExist raise self._obj.model.DoesNotExist
raise self._obj.model.MultipleObjectsReturned raise self._obj.model.MultipleObjectsReturned
@modifies_query
def order_by(self, *args): def order_by(self, *args):
return self._wrap_queryset(self.get_queryset().order_by(*args)) return self._wrap_queryset(self.get_queryset().order_by(*args))
@ -413,42 +384,33 @@ class BaseQueryWrapper(BaseWrapper):
tuple(self._filter_kwarg(name, value) for name, value in kwargs.items()) tuple(self._filter_kwarg(name, value) for name, value in kwargs.items())
) )
@modifies_query
def filter(self, *args, **kwargs): def filter(self, *args, **kwargs):
return self._wrap_queryset(self.get_queryset().filter(*self._filter(*args, **kwargs))) return self._wrap_queryset(self.get_queryset().filter(*self._filter(*args, **kwargs)))
@modifies_query
def exclude(self, *args, **kwargs): def exclude(self, *args, **kwargs):
return self._wrap_queryset(self.get_queryset().exclude(*self._filter(*args, **kwargs))) return self._wrap_queryset(self.get_queryset().exclude(*self._filter(*args, **kwargs)))
@executes_query
def count(self): def count(self):
return self.get_queryset().count() return self.get_queryset().count()
@executes_query
def values_list(self, *args, flat=False): def values_list(self, *args, flat=False):
return self.get_queryset().values_list(*args, flat=flat) return self.get_queryset().values_list(*args, flat=flat)
@executes_query
def first(self): def first(self):
first = self.get_queryset().first() first = self.get_queryset().first()
if first is not None: if first is not None:
first = self._wrap_instance(first) first = self._wrap_instance(first)
return first return first
@modifies_query
def using(self, alias): def using(self, alias):
return self._wrap_queryset(self.get_queryset().using(alias)) return self._wrap_queryset(self.get_queryset().using(alias))
@executes_query
def __iter__(self): def __iter__(self):
return iter((self._wrap_instance(instance) for instance in self.get_queryset())) return iter((self._wrap_instance(instance) for instance in self.get_queryset()))
@executes_query
def iterator(self): def iterator(self):
return iter((self._wrap_instance(instance) for instance in self.get_queryset().iterator())) return iter((self._wrap_instance(instance) for instance in self.get_queryset().iterator()))
@executes_query
def __len__(self): def __len__(self):
return len(self.get_queryset()) return len(self.get_queryset())