From 760e28e72bae475b442b026650969b0d182dbe53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anssi=20K=C3=A4=C3=A4ri=C3=A4inen?= Date: Sun, 1 Dec 2013 20:04:31 +0200 Subject: [PATCH] Removed usage of Constraint, used Lookup instead --- django/contrib/contenttypes/generic.py | 5 +++-- django/db/models/fields/related.py | 26 +++++++++++++------------- django/db/models/sql/datastructures.py | 3 +++ django/db/models/sql/query.py | 19 +++++++++++-------- django/db/models/sql/subqueries.py | 20 ++++++++------------ django/db/models/sql/where.py | 8 ++++++++ 6 files changed, 46 insertions(+), 35 deletions(-) diff --git a/django/contrib/contenttypes/generic.py b/django/contrib/contenttypes/generic.py index 9ef499bb16095..a310de2fb2ffb 100644 --- a/django/contrib/contenttypes/generic.py +++ b/django/contrib/contenttypes/generic.py @@ -12,7 +12,7 @@ from django.db.models import signals from django.db.models.fields.related import ForeignObject, ForeignObjectRel from django.db.models.related import PathInfo -from django.db.models.sql.where import Constraint +from django.db.models.sql.datastructures import Col from django.forms import ModelForm, ALL_FIELDS from django.forms.models import (BaseModelFormSet, modelformset_factory, modelform_defines_fields) @@ -236,7 +236,8 @@ def get_extra_restriction(self, where_class, alias, remote_alias): field = self.rel.to._meta.get_field_by_name(self.content_type_field_name)[0] contenttype_pk = self.get_content_type().pk cond = where_class() - cond.add((Constraint(remote_alias, field.column, field), 'exact', contenttype_pk), 'AND') + lookup = field.get_lookup('exact')(Col(remote_alias, field, field), contenttype_pk) + cond.add(lookup, 'AND') return cond def bulk_related_objects(self, objs, using=DEFAULT_DB_ALIAS): diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 29016301ed800..a2d0a8dcd0af6 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -5,9 +5,11 @@ from django.db.models import signals, Q from django.db.models.fields import (AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, FieldDoesNotExist) +from django.db.models.lookups import IsNull from django.db.models.related import RelatedObject, PathInfo from django.db.models.query import QuerySet from django.db.models.deletion import CASCADE +from django.db.models.sql.datastructures import Col from django.utils.encoding import smart_text from django.utils import six from django.utils.deprecation import RenameMethodsBase @@ -1138,7 +1140,7 @@ def get_reverse_path_info(self): def get_lookup_constraint(self, constraint_class, alias, targets, sources, lookups, raw_value): - from django.db.models.sql.where import SubqueryConstraint, Constraint, AND, OR + from django.db.models.sql.where import SubqueryConstraint, AND, OR root_constraint = constraint_class() assert len(targets) == len(sources) if len(lookups) > 1: @@ -1146,7 +1148,6 @@ def get_lookup_constraint(self, constraint_class, alias, targets, sources, looku lookup_type = lookups[0] def get_normalized_value(value): - from django.db.models import Model if isinstance(value, Model): value_list = [] @@ -1167,28 +1168,27 @@ def get_normalized_value(value): [source.name for source in sources], raw_value), AND) elif lookup_type == 'isnull': - root_constraint.add( - (Constraint(alias, targets[0].column, targets[0]), lookup_type, raw_value), AND) + root_constraint.add(IsNull(Col(alias, targets[0], sources[0]), raw_value), AND) elif (lookup_type == 'exact' or (lookup_type in ['gt', 'lt', 'gte', 'lte'] and not is_multicolumn)): value = get_normalized_value(raw_value) - for index, source in enumerate(sources): + for target, source, val in zip(targets, sources, value): + lookup_class = target.get_lookup(lookup_type) root_constraint.add( - (Constraint(alias, targets[index].column, sources[index]), lookup_type, - value[index]), AND) + lookup_class(Col(alias, target, source), val), AND) elif lookup_type in ['range', 'in'] and not is_multicolumn: values = [get_normalized_value(value) for value in raw_value] value = [val[0] for val in values] - root_constraint.add( - (Constraint(alias, targets[0].column, sources[0]), lookup_type, value), AND) + lookup_class = targets[0].get_lookup(lookup_type) + root_constraint.add(lookup_class(Col(alias, targets[0], sources[0]), value), AND) elif lookup_type == 'in': values = [get_normalized_value(value) for value in raw_value] for value in values: value_constraint = constraint_class() - for index, target in enumerate(targets): - value_constraint.add( - (Constraint(alias, target.column, sources[index]), 'exact', value[index]), - AND) + for source, target, val in zip(sources, targets, value): + lookup_class = target.get_lookup('exact') + lookup = lookup_class(Col(alias, target, source), val) + value_constraint.add(lookup, AND) root_constraint.add(value_constraint, OR) else: raise TypeError('Related Field got invalid lookup: %s' % lookup_type) diff --git a/django/db/models/sql/datastructures.py b/django/db/models/sql/datastructures.py index 1e1573f1e6d7a..912e4ba5d2a6c 100644 --- a/django/db/models/sql/datastructures.py +++ b/django/db/models/sql/datastructures.py @@ -28,6 +28,9 @@ def get_cols(self): def get_lookup(self, name): return self.output_type.get_lookup(name) + def prepare(self): + return self + class EmptyResultSet(Exception): pass diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 971db28ae1230..2832a86fd26b4 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1211,7 +1211,8 @@ def build_filter(self, filter_expr, branch_negated=False, current_negated=False, # (col IS NULL OR col != someval) # <=> # NOT (col IS NOT NULL AND col = someval). - clause.add((Constraint(alias, targets[0].column, None), 'isnull', False), AND) + lookup_class = targets[0].get_lookup('isnull') + clause.add(lookup_class(Col(alias, targets[0], sources[0]), False), AND) return clause, used_joins if not require_outer else () def add_filter(self, filter_clause): @@ -1486,17 +1487,19 @@ def split_exclude(self, filter_expr, prefix, can_reuse, names_with_path): # nothing alias, col = query.select[0].col if self.is_nullable(query.select[0].field): - query.where.add((Constraint(alias, col, query.select[0].field), 'isnull', False), AND) + lookup_class = query.select[0].field.get_lookup('isnull') + lookup = lookup_class(Col(alias, query.select[0].field, query.select[0].field), False) + query.where.add(lookup, AND) if alias in can_reuse: - pk = query.select[0].field.model._meta.pk + select_field = query.select[0].field + pk = select_field.model._meta.pk # Need to add a restriction so that outer query's filters are in effect for # the subquery, too. query.bump_prefix(self) - query.where.add( - (Constraint(query.select[0].col[0], pk.column, pk), - 'exact', Col(alias, pk, pk)), - AND - ) + lookup_class = select_field.get_lookup('exact') + lookup = lookup_class(Col(query.select[0].col[0], pk, pk), + Col(alias, pk, pk)) + query.where.add(lookup, AND) condition, needed_inner = self.build_filter( ('%s__in' % trimmed_prefix, query), diff --git a/django/db/models/sql/subqueries.py b/django/db/models/sql/subqueries.py index 79db1ad99a49c..7130f7472e82a 100644 --- a/django/db/models/sql/subqueries.py +++ b/django/db/models/sql/subqueries.py @@ -5,12 +5,12 @@ from django.conf import settings from django.core.exceptions import FieldError from django.db import connections +from django.db.models.query_utils import Q from django.db.models.constants import LOOKUP_SEP from django.db.models.fields import DateField, DateTimeField, FieldDoesNotExist from django.db.models.sql.constants import GET_ITERATOR_CHUNK_SIZE, SelectInfo from django.db.models.sql.datastructures import Date, DateTime from django.db.models.sql.query import Query -from django.db.models.sql.where import AND, Constraint from django.utils import six from django.utils import timezone @@ -42,10 +42,10 @@ def delete_batch(self, pk_list, using, field=None): if not field: field = self.get_meta().pk for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): - where = self.where_class() - where.add((Constraint(None, field.column, field), 'in', - pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE]), AND) - self.do_query(self.get_meta().db_table, where, using=using) + self.where = self.where_class() + self.add_q(Q( + **{field.attname + '__in': pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE]})) + self.do_query(self.get_meta().db_table, self.where, using=using) def delete_qs(self, query, using): """ @@ -80,9 +80,8 @@ def delete_qs(self, query, using): SelectInfo((self.get_initial_alias(), pk.column), None) ] values = innerq - where = self.where_class() - where.add((Constraint(None, pk.column, pk), 'in', values), AND) - self.where = where + self.where = self.where_class() + self.add_q(Q(pk__in=values)) self.get_compiler(using).execute_sql(None) @@ -113,13 +112,10 @@ def clone(self, klass=None, **kwargs): related_updates=self.related_updates.copy(), **kwargs) def update_batch(self, pk_list, values, using): - pk_field = self.get_meta().pk self.add_update_values(values) for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): self.where = self.where_class() - self.where.add((Constraint(None, pk_field.column, pk_field), 'in', - pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE]), - AND) + self.add_q(Q(pk__in=pk_list[offset: offset + GET_ITERATOR_CHUNK_SIZE])) self.get_compiler(using).execute_sql(None) def add_update_values(self, values): diff --git a/django/db/models/sql/where.py b/django/db/models/sql/where.py index 637b851830444..a8ddf7135073d 100644 --- a/django/db/models/sql/where.py +++ b/django/db/models/sql/where.py @@ -5,6 +5,7 @@ import collections import datetime from itertools import repeat +import warnings from django.conf import settings from django.db.models.fields import DateTimeField, Field @@ -174,6 +175,9 @@ def make_atom(self, child, qn, connection): Returns the string for the SQL fragment and the parameters to use for it. """ + warnings.warn( + "The make_atom() method will be removed in Django 1.9. Use Lookup class instead.", + PendingDeprecationWarning) lvalue, lookup_type, value_annotation, params_or_value = child field_internal_type = lvalue.field.get_internal_type() if lvalue.field else None @@ -349,6 +353,10 @@ class Constraint(object): pre-process itself prior to including in the WhereNode. """ def __init__(self, alias, col, field): + warnings.warn( + "The Constraint class will be removed in Django 1.9. Use Lookup class instead.", + PendingDeprecationWarning) + import ipdb; ipdb.set_trace() self.alias, self.col, self.field = alias, col, field def prepare(self, lookup_type, value):