1
0
mirror of https://github.com/django/django.git synced 2025-06-16 00:49:12 +00:00

Removed usage of Constraint, used Lookup instead

This commit is contained in:
Anssi Kääriäinen 2013-12-01 20:04:31 +02:00
parent eac4776684
commit 760e28e72b
6 changed files with 46 additions and 35 deletions

View File

@ -12,7 +12,7 @@ from django.db import models, router, transaction, DEFAULT_DB_ALIAS
from django.db.models import signals from django.db.models import signals
from django.db.models.fields.related import ForeignObject, ForeignObjectRel from django.db.models.fields.related import ForeignObject, ForeignObjectRel
from django.db.models.related import PathInfo 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 import ModelForm, ALL_FIELDS
from django.forms.models import (BaseModelFormSet, modelformset_factory, from django.forms.models import (BaseModelFormSet, modelformset_factory,
modelform_defines_fields) modelform_defines_fields)
@ -236,7 +236,8 @@ class GenericRelation(ForeignObject):
field = self.rel.to._meta.get_field_by_name(self.content_type_field_name)[0] field = self.rel.to._meta.get_field_by_name(self.content_type_field_name)[0]
contenttype_pk = self.get_content_type().pk contenttype_pk = self.get_content_type().pk
cond = where_class() 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 return cond
def bulk_related_objects(self, objs, using=DEFAULT_DB_ALIAS): def bulk_related_objects(self, objs, using=DEFAULT_DB_ALIAS):

View File

@ -5,9 +5,11 @@ from django.db.backends import utils
from django.db.models import signals, Q from django.db.models import signals, Q
from django.db.models.fields import (AutoField, Field, IntegerField, from django.db.models.fields import (AutoField, Field, IntegerField,
PositiveIntegerField, PositiveSmallIntegerField, FieldDoesNotExist) PositiveIntegerField, PositiveSmallIntegerField, FieldDoesNotExist)
from django.db.models.lookups import IsNull
from django.db.models.related import RelatedObject, PathInfo from django.db.models.related import RelatedObject, PathInfo
from django.db.models.query import QuerySet from django.db.models.query import QuerySet
from django.db.models.deletion import CASCADE 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.encoding import smart_text
from django.utils import six from django.utils import six
from django.utils.deprecation import RenameMethodsBase from django.utils.deprecation import RenameMethodsBase
@ -1138,7 +1140,7 @@ class ForeignObject(RelatedField):
def get_lookup_constraint(self, constraint_class, alias, targets, sources, lookups, def get_lookup_constraint(self, constraint_class, alias, targets, sources, lookups,
raw_value): 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() root_constraint = constraint_class()
assert len(targets) == len(sources) assert len(targets) == len(sources)
if len(lookups) > 1: if len(lookups) > 1:
@ -1146,7 +1148,6 @@ class ForeignObject(RelatedField):
lookup_type = lookups[0] lookup_type = lookups[0]
def get_normalized_value(value): def get_normalized_value(value):
from django.db.models import Model from django.db.models import Model
if isinstance(value, Model): if isinstance(value, Model):
value_list = [] value_list = []
@ -1167,28 +1168,27 @@ class ForeignObject(RelatedField):
[source.name for source in sources], raw_value), [source.name for source in sources], raw_value),
AND) AND)
elif lookup_type == 'isnull': elif lookup_type == 'isnull':
root_constraint.add( root_constraint.add(IsNull(Col(alias, targets[0], sources[0]), raw_value), AND)
(Constraint(alias, targets[0].column, targets[0]), lookup_type, raw_value), AND)
elif (lookup_type == 'exact' or (lookup_type in ['gt', 'lt', 'gte', 'lte'] elif (lookup_type == 'exact' or (lookup_type in ['gt', 'lt', 'gte', 'lte']
and not is_multicolumn)): and not is_multicolumn)):
value = get_normalized_value(raw_value) 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( root_constraint.add(
(Constraint(alias, targets[index].column, sources[index]), lookup_type, lookup_class(Col(alias, target, source), val), AND)
value[index]), AND)
elif lookup_type in ['range', 'in'] and not is_multicolumn: elif lookup_type in ['range', 'in'] and not is_multicolumn:
values = [get_normalized_value(value) for value in raw_value] values = [get_normalized_value(value) for value in raw_value]
value = [val[0] for val in values] value = [val[0] for val in values]
root_constraint.add( lookup_class = targets[0].get_lookup(lookup_type)
(Constraint(alias, targets[0].column, sources[0]), lookup_type, value), AND) root_constraint.add(lookup_class(Col(alias, targets[0], sources[0]), value), AND)
elif lookup_type == 'in': elif lookup_type == 'in':
values = [get_normalized_value(value) for value in raw_value] values = [get_normalized_value(value) for value in raw_value]
for value in values: for value in values:
value_constraint = constraint_class() value_constraint = constraint_class()
for index, target in enumerate(targets): for source, target, val in zip(sources, targets, value):
value_constraint.add( lookup_class = target.get_lookup('exact')
(Constraint(alias, target.column, sources[index]), 'exact', value[index]), lookup = lookup_class(Col(alias, target, source), val)
AND) value_constraint.add(lookup, AND)
root_constraint.add(value_constraint, OR) root_constraint.add(value_constraint, OR)
else: else:
raise TypeError('Related Field got invalid lookup: %s' % lookup_type) raise TypeError('Related Field got invalid lookup: %s' % lookup_type)

View File

@ -28,6 +28,9 @@ class Col(object):
def get_lookup(self, name): def get_lookup(self, name):
return self.output_type.get_lookup(name) return self.output_type.get_lookup(name)
def prepare(self):
return self
class EmptyResultSet(Exception): class EmptyResultSet(Exception):
pass pass

View File

@ -1211,7 +1211,8 @@ class Query(object):
# (col IS NULL OR col != someval) # (col IS NULL OR col != someval)
# <=> # <=>
# NOT (col IS NOT NULL AND 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 () return clause, used_joins if not require_outer else ()
def add_filter(self, filter_clause): def add_filter(self, filter_clause):
@ -1486,17 +1487,19 @@ class Query(object):
# nothing # nothing
alias, col = query.select[0].col alias, col = query.select[0].col
if self.is_nullable(query.select[0].field): 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: 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 # Need to add a restriction so that outer query's filters are in effect for
# the subquery, too. # the subquery, too.
query.bump_prefix(self) query.bump_prefix(self)
query.where.add( lookup_class = select_field.get_lookup('exact')
(Constraint(query.select[0].col[0], pk.column, pk), lookup = lookup_class(Col(query.select[0].col[0], pk, pk),
'exact', Col(alias, pk, pk)), Col(alias, pk, pk))
AND query.where.add(lookup, AND)
)
condition, needed_inner = self.build_filter( condition, needed_inner = self.build_filter(
('%s__in' % trimmed_prefix, query), ('%s__in' % trimmed_prefix, query),

View File

@ -5,12 +5,12 @@ Query subclasses which provide extra functionality beyond simple data retrieval.
from django.conf import settings from django.conf import settings
from django.core.exceptions import FieldError from django.core.exceptions import FieldError
from django.db import connections 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.constants import LOOKUP_SEP
from django.db.models.fields import DateField, DateTimeField, FieldDoesNotExist 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.constants import GET_ITERATOR_CHUNK_SIZE, SelectInfo
from django.db.models.sql.datastructures import Date, DateTime from django.db.models.sql.datastructures import Date, DateTime
from django.db.models.sql.query import Query 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 six
from django.utils import timezone from django.utils import timezone
@ -42,10 +42,10 @@ class DeleteQuery(Query):
if not field: if not field:
field = self.get_meta().pk field = self.get_meta().pk
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
where = self.where_class() self.where = self.where_class()
where.add((Constraint(None, field.column, field), 'in', self.add_q(Q(
pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE]), AND) **{field.attname + '__in': pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE]}))
self.do_query(self.get_meta().db_table, where, using=using) self.do_query(self.get_meta().db_table, self.where, using=using)
def delete_qs(self, query, using): def delete_qs(self, query, using):
""" """
@ -80,9 +80,8 @@ class DeleteQuery(Query):
SelectInfo((self.get_initial_alias(), pk.column), None) SelectInfo((self.get_initial_alias(), pk.column), None)
] ]
values = innerq values = innerq
where = self.where_class() self.where = self.where_class()
where.add((Constraint(None, pk.column, pk), 'in', values), AND) self.add_q(Q(pk__in=values))
self.where = where
self.get_compiler(using).execute_sql(None) self.get_compiler(using).execute_sql(None)
@ -113,13 +112,10 @@ class UpdateQuery(Query):
related_updates=self.related_updates.copy(), **kwargs) related_updates=self.related_updates.copy(), **kwargs)
def update_batch(self, pk_list, values, using): def update_batch(self, pk_list, values, using):
pk_field = self.get_meta().pk
self.add_update_values(values) self.add_update_values(values)
for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE):
self.where = self.where_class() self.where = self.where_class()
self.where.add((Constraint(None, pk_field.column, pk_field), 'in', self.add_q(Q(pk__in=pk_list[offset: offset + GET_ITERATOR_CHUNK_SIZE]))
pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE]),
AND)
self.get_compiler(using).execute_sql(None) self.get_compiler(using).execute_sql(None)
def add_update_values(self, values): def add_update_values(self, values):

View File

@ -5,6 +5,7 @@ Code to manage the creation and SQL rendering of 'where' constraints.
import collections import collections
import datetime import datetime
from itertools import repeat from itertools import repeat
import warnings
from django.conf import settings from django.conf import settings
from django.db.models.fields import DateTimeField, Field from django.db.models.fields import DateTimeField, Field
@ -174,6 +175,9 @@ class WhereNode(tree.Node):
Returns the string for the SQL fragment and the parameters to use for Returns the string for the SQL fragment and the parameters to use for
it. 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 lvalue, lookup_type, value_annotation, params_or_value = child
field_internal_type = lvalue.field.get_internal_type() if lvalue.field else None 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. pre-process itself prior to including in the WhereNode.
""" """
def __init__(self, alias, col, field): 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 self.alias, self.col, self.field = alias, col, field
def prepare(self, lookup_type, value): def prepare(self, lookup_type, value):