Added Query.is_sliced property.
Previously, we used Query.can_filter() mainly to check if a query is sliced what was confusing.
This commit is contained in:
parent
1853383969
commit
806ba19bbf
|
@ -635,7 +635,7 @@ class QuerySet:
|
|||
"arguments or 'get_latest_by' in the model's Meta."
|
||||
)
|
||||
|
||||
assert self.query.can_filter(), \
|
||||
assert not self.query.is_sliced, \
|
||||
"Cannot change a query once a slice has been taken."
|
||||
obj = self._chain()
|
||||
obj.query.set_limits(high=1)
|
||||
|
@ -664,7 +664,7 @@ class QuerySet:
|
|||
Return a dictionary mapping each of the given IDs to the object with
|
||||
that ID. If `id_list` isn't provided, evaluate the entire QuerySet.
|
||||
"""
|
||||
assert self.query.can_filter(), \
|
||||
assert not self.query.is_sliced, \
|
||||
"Cannot use 'limit' or 'offset' with in_bulk"
|
||||
if field_name != 'pk' and not self.model._meta.get_field(field_name).unique:
|
||||
raise ValueError("in_bulk()'s field_name must be a unique field but %r isn't." % field_name)
|
||||
|
@ -689,7 +689,7 @@ class QuerySet:
|
|||
|
||||
def delete(self):
|
||||
"""Delete the records in the current QuerySet."""
|
||||
assert self.query.can_filter(), \
|
||||
assert not self.query.is_sliced, \
|
||||
"Cannot use 'limit' or 'offset' with delete."
|
||||
|
||||
if self._fields is not None:
|
||||
|
@ -731,7 +731,7 @@ class QuerySet:
|
|||
Update all elements in the current QuerySet, setting all the given
|
||||
fields to the appropriate values.
|
||||
"""
|
||||
assert self.query.can_filter(), \
|
||||
assert not self.query.is_sliced, \
|
||||
"Cannot update a query once a slice has been taken."
|
||||
self._for_write = True
|
||||
query = self.query.chain(sql.UpdateQuery)
|
||||
|
@ -751,7 +751,7 @@ class QuerySet:
|
|||
code (it requires too much poking around at model internals to be
|
||||
useful at that level).
|
||||
"""
|
||||
assert self.query.can_filter(), \
|
||||
assert not self.query.is_sliced, \
|
||||
"Cannot update a query once a slice has been taken."
|
||||
query = self.query.chain(sql.UpdateQuery)
|
||||
query.add_update_fields(values)
|
||||
|
@ -903,7 +903,7 @@ class QuerySet:
|
|||
|
||||
def _filter_or_exclude(self, negate, *args, **kwargs):
|
||||
if args or kwargs:
|
||||
assert self.query.can_filter(), \
|
||||
assert not self.query.is_sliced, \
|
||||
"Cannot filter a query once a slice has been taken."
|
||||
|
||||
clone = self._chain()
|
||||
|
@ -1072,7 +1072,7 @@ class QuerySet:
|
|||
|
||||
def order_by(self, *field_names):
|
||||
"""Return a new QuerySet instance with the ordering changed."""
|
||||
assert self.query.can_filter(), \
|
||||
assert not self.query.is_sliced, \
|
||||
"Cannot reorder a query once a slice has been taken."
|
||||
obj = self._chain()
|
||||
obj.query.clear_ordering(force_empty=False)
|
||||
|
@ -1083,7 +1083,7 @@ class QuerySet:
|
|||
"""
|
||||
Return a new QuerySet instance that will select only distinct results.
|
||||
"""
|
||||
assert self.query.can_filter(), \
|
||||
assert not self.query.is_sliced, \
|
||||
"Cannot create distinct fields once a slice has been taken."
|
||||
obj = self._chain()
|
||||
obj.query.add_distinct_fields(*field_names)
|
||||
|
@ -1093,7 +1093,7 @@ class QuerySet:
|
|||
order_by=None, select_params=None):
|
||||
"""Add extra SQL fragments to the query."""
|
||||
self._not_support_combined_queries('extra')
|
||||
assert self.query.can_filter(), \
|
||||
assert not self.query.is_sliced, \
|
||||
"Cannot change a query once a slice has been taken"
|
||||
clone = self._chain()
|
||||
clone.query.add_extra(select, select_params, where, params, tables, order_by)
|
||||
|
@ -1101,7 +1101,7 @@ class QuerySet:
|
|||
|
||||
def reverse(self):
|
||||
"""Reverse the ordering of the QuerySet."""
|
||||
if not self.query.can_filter():
|
||||
if self.query.is_sliced:
|
||||
raise TypeError('Cannot reverse a query once a slice has been taken.')
|
||||
clone = self._chain()
|
||||
clone.query.standard_ordering = not clone.query.standard_ordering
|
||||
|
|
|
@ -413,7 +413,6 @@ class Query(BaseExpression):
|
|||
"""
|
||||
if not self.annotation_select:
|
||||
return {}
|
||||
has_limit = self.low_mark != 0 or self.high_mark is not None
|
||||
existing_annotations = [
|
||||
annotation for alias, annotation
|
||||
in self.annotations.items()
|
||||
|
@ -430,7 +429,7 @@ class Query(BaseExpression):
|
|||
# those operations must be done in a subquery so that the query
|
||||
# aggregates on the limit and/or distinct results instead of applying
|
||||
# the distinct and limit after the aggregation.
|
||||
if (isinstance(self.group_by, tuple) or has_limit or existing_annotations or
|
||||
if (isinstance(self.group_by, tuple) or self.is_sliced or existing_annotations or
|
||||
self.distinct or self.combinator):
|
||||
from django.db.models.sql.subqueries import AggregateQuery
|
||||
outer_query = AggregateQuery(self.model)
|
||||
|
@ -438,7 +437,7 @@ class Query(BaseExpression):
|
|||
inner_query.select_for_update = False
|
||||
inner_query.select_related = False
|
||||
inner_query.set_annotation_mask(self.annotation_select)
|
||||
if not has_limit and not self.distinct_fields:
|
||||
if not self.is_sliced and not self.distinct_fields:
|
||||
# Queries with distinct_fields need ordering and when a limit
|
||||
# is applied we must take the slice from the ordered query.
|
||||
# Otherwise no need for ordering.
|
||||
|
@ -548,7 +547,7 @@ class Query(BaseExpression):
|
|||
"""
|
||||
assert self.model == rhs.model, \
|
||||
"Cannot combine queries on two different base models."
|
||||
assert self.can_filter(), \
|
||||
assert not self.is_sliced, \
|
||||
"Cannot combine queries once a slice has been taken."
|
||||
assert self.distinct == rhs.distinct, \
|
||||
"Cannot combine a unique query with a non-unique query."
|
||||
|
@ -1762,6 +1761,10 @@ class Query(BaseExpression):
|
|||
"""Clear any existing limits."""
|
||||
self.low_mark, self.high_mark = 0, None
|
||||
|
||||
@property
|
||||
def is_sliced(self):
|
||||
return self.low_mark != 0 or self.high_mark is not None
|
||||
|
||||
def has_limit_one(self):
|
||||
return self.high_mark is not None and (self.high_mark - self.low_mark) == 1
|
||||
|
||||
|
@ -1771,7 +1774,7 @@ class Query(BaseExpression):
|
|||
|
||||
Typically, this means no limits or offsets have been put on the results.
|
||||
"""
|
||||
return not self.low_mark and self.high_mark is None
|
||||
return not self.is_sliced
|
||||
|
||||
def clear_select_clause(self):
|
||||
"""Remove all fields from SELECT clause."""
|
||||
|
|
Loading…
Reference in New Issue