1
0
mirror of https://github.com/django/django.git synced 2025-10-24 06:06:09 +00:00

Fixed #22936 -- Obsoleted Field.get_prep_lookup()/get_db_prep_lookup()

Thanks Tim Graham for completing the initial patch.
This commit is contained in:
Claude Paroz
2016-04-23 19:13:31 +02:00
parent 1206eea11e
commit 388bb5bd9a
19 changed files with 89 additions and 220 deletions

View File

@@ -232,6 +232,9 @@ class BooleanFieldListFilter(FieldListFilter):
self.lookup_val = request.GET.get(self.lookup_kwarg)
self.lookup_val2 = request.GET.get(self.lookup_kwarg2)
super(BooleanFieldListFilter, self).__init__(field, request, params, model, model_admin, field_path)
if (self.used_parameters and self.lookup_kwarg in self.used_parameters and
self.used_parameters[self.lookup_kwarg] in ('1', '0')):
self.used_parameters[self.lookup_kwarg] = bool(int(self.used_parameters[self.lookup_kwarg]))
def expected_parameters(self):
return [self.lookup_kwarg, self.lookup_kwarg2]

View File

@@ -128,7 +128,6 @@ def url_params_from_lookup_dict(lookups):
if isinstance(v, (tuple, list)):
v = ','.join(str(x) for x in v)
elif isinstance(v, bool):
# See django.db.fields.BooleanField.get_prep_lookup
v = ('0', '1')[v]
else:
v = six.text_type(v)

View File

@@ -316,13 +316,6 @@ class GeometryField(GeoSelectFormatMixin, BaseSpatialField):
params = [connection.ops.Adapter(value)]
return params
def get_prep_lookup(self, lookup_type, value):
if lookup_type == 'contains':
# 'contains' name might conflict with the "normal" contains lookup,
# for which the value is not prepared, but left as-is.
return self.get_prep_value(value)
return super(GeometryField, self).get_prep_lookup(lookup_type, value)
def get_db_prep_save(self, value, connection):
"Prepares the value for saving in the database."
if not value:

View File

@@ -31,13 +31,6 @@ class JSONField(Field):
return Json(value)
return value
def get_prep_lookup(self, lookup_type, value):
if lookup_type in ('has_key', 'has_keys', 'has_any_keys'):
return value
if isinstance(value, (dict, list)):
return Json(value)
return super(JSONField, self).get_prep_lookup(lookup_type, value)
def validate(self, value, model_instance):
super(JSONField, self).validate(value, model_instance)
try:

View File

@@ -154,7 +154,7 @@ class RangeContainedBy(models.Lookup):
return sql % (lhs, rhs), params
def get_prep_lookup(self):
return RangeField().get_prep_lookup(self.lookup_name, self.rhs)
return RangeField().get_prep_value(self.rhs)
models.DateField.register_lookup(RangeContainedBy)

View File

@@ -1,4 +1,5 @@
from django.db.models import Lookup, Transform
from django.utils.encoding import force_text
from .search import SearchVector, SearchVectorExact, SearchVectorField
@@ -29,14 +30,18 @@ class Overlap(PostgresSimpleLookup):
class HasKey(PostgresSimpleLookup):
lookup_name = 'has_key'
operator = '?'
prepare_rhs = False
class HasKeys(PostgresSimpleLookup):
lookup_name = 'has_keys'
operator = '?&'
def get_prep_lookup(self):
return [force_text(item) for item in self.rhs]
class HasAnyKeys(PostgresSimpleLookup):
class HasAnyKeys(HasKeys):
lookup_name = 'has_any_keys'
operator = '?|'

View File

@@ -213,7 +213,7 @@ class BaseExpression(object):
def _prepare(self, field):
"""
Hook used by Field.get_prep_lookup() to do custom preparation.
Hook used by Lookup.get_prep_lookup() to do custom preparation.
"""
return self

View File

@@ -741,8 +741,7 @@ class Field(RegisterLookupMixin):
"""Returns field's value prepared for interacting with the database
backend.
Used by the default implementations of ``get_db_prep_save``and
`get_db_prep_lookup```
Used by the default implementations of get_db_prep_save().
"""
if not prepared:
value = self.get_prep_value(value)
@@ -755,36 +754,6 @@ class Field(RegisterLookupMixin):
return self.get_db_prep_value(value, connection=connection,
prepared=False)
def get_prep_lookup(self, lookup_type, value):
"""
Perform preliminary non-db specific lookup checks and conversions
"""
if hasattr(value, '_prepare'):
return value._prepare(self)
if lookup_type in {
'iexact', 'contains', 'icontains',
'startswith', 'istartswith', 'endswith', 'iendswith',
'isnull', 'search', 'regex', 'iregex',
}:
return value
elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'):
return self.get_prep_value(value)
elif lookup_type in ('range', 'in'):
return [self.get_prep_value(v) for v in value]
return self.get_prep_value(value)
def get_db_prep_lookup(self, lookup_type, value, connection,
prepared=False):
"""
Returns field's value prepared for database lookup.
"""
if not prepared:
value = self.get_prep_lookup(lookup_type, value)
prepared = True
return [value]
def has_default(self):
"""
Returns a boolean of whether this field has a default value.
@@ -1049,20 +1018,11 @@ class BooleanField(Field):
params={'value': value},
)
def get_prep_lookup(self, lookup_type, value):
# Special-case handling for filters coming from a Web request (e.g. the
# admin interface). Only works for scalar values (not lists). If you're
# passing in a list, you might as well make things the right type when
# constructing the list.
if value in ('1', '0'):
value = bool(int(value))
return super(BooleanField, self).get_prep_lookup(lookup_type, value)
def get_prep_value(self, value):
value = super(BooleanField, self).get_prep_value(value)
if value is None:
return None
return bool(value)
return self.to_python(value)
def formfield(self, **kwargs):
# Unlike most fields, BooleanField figures out include_blank from
@@ -1453,8 +1413,6 @@ class DateTimeField(DateField):
# contribute_to_class is inherited from DateField, it registers
# get_next_by_FOO and get_prev_by_FOO
# get_prep_lookup is inherited from DateField
def get_prep_value(self, value):
value = super(DateTimeField, self).get_prep_value(value)
value = self.to_python(value)
@@ -2051,21 +2009,11 @@ class NullBooleanField(Field):
params={'value': value},
)
def get_prep_lookup(self, lookup_type, value):
# Special-case handling for filters coming from a Web request (e.g. the
# admin interface). Only works for scalar values (not lists). If you're
# passing in a list, you might as well make things the right type when
# constructing the list.
if value in ('1', '0'):
value = bool(int(value))
return super(NullBooleanField, self).get_prep_lookup(lookup_type,
value)
def get_prep_value(self, value):
value = super(NullBooleanField, self).get_prep_value(value)
if value is None:
return None
return bool(value)
return self.to_python(value)
def formfield(self, **kwargs):
defaults = {

View File

@@ -271,11 +271,6 @@ class FileField(Field):
def get_internal_type(self):
return "FileField"
def get_prep_lookup(self, lookup_type, value):
if hasattr(value, 'name'):
value = value.name
return super(FileField, self).get_prep_lookup(lookup_type, value)
def get_prep_value(self, value):
"Returns field's value prepared for saving into a database."
value = super(FileField, self).get_prep_value(value)

View File

@@ -44,15 +44,15 @@ class RelatedIn(In):
if not isinstance(self.lhs, MultiColSource) and self.rhs_is_direct_value():
# If we get here, we are dealing with single-column relations.
self.rhs = [get_normalized_value(val, self.lhs)[0] for val in self.rhs]
# We need to run the related field's get_prep_lookup(). Consider case
# We need to run the related field's get_prep_value(). Consider case
# ForeignKey to IntegerField given value 'abc'. The ForeignKey itself
# doesn't have validation for non-integers, so we must run validation
# using the target field.
if hasattr(self.lhs.output_field, 'get_path_info'):
# Run the target field's get_prep_lookup. We can safely assume there is
# Run the target field's get_prep_value. We can safely assume there is
# only one as we don't get to the direct value branch otherwise.
self.rhs = self.lhs.output_field.get_path_info()[-1].target_fields[-1].get_prep_lookup(
self.lookup_name, self.rhs)
target_field = self.lhs.output_field.get_path_info()[-1].target_fields[-1]
self.rhs = [target_field.get_prep_value(v) for v in self.rhs]
return super(RelatedIn, self).get_prep_lookup()
def as_sql(self, compiler, connection):
@@ -88,15 +88,15 @@ class RelatedLookupMixin(object):
if not isinstance(self.lhs, MultiColSource) and self.rhs_is_direct_value():
# If we get here, we are dealing with single-column relations.
self.rhs = get_normalized_value(self.rhs, self.lhs)[0]
# We need to run the related field's get_prep_lookup(). Consider case
# We need to run the related field's get_prep_value(). Consider case
# ForeignKey to IntegerField given value 'abc'. The ForeignKey itself
# doesn't have validation for non-integers, so we must run validation
# using the target field.
if hasattr(self.lhs.output_field, 'get_path_info'):
# Get the target field. We can safely assume there is only one
# as we don't get to the direct value branch otherwise.
self.rhs = self.lhs.output_field.get_path_info()[-1].target_fields[-1].get_prep_lookup(
self.lookup_name, self.rhs)
target_field = self.lhs.output_field.get_path_info()[-1].target_fields[-1]
self.rhs = target_field.get_prep_value(self.rhs)
return super(RelatedLookupMixin, self).get_prep_lookup()

View File

@@ -110,9 +110,6 @@ class ForeignObjectRel(object):
def one_to_one(self):
return self.field.one_to_one
def get_prep_lookup(self, lookup_name, value):
return self.field.get_prep_lookup(lookup_name, value)
def get_lookup(self, lookup_name):
return self.field.get_lookup(lookup_name)
@@ -142,10 +139,6 @@ class ForeignObjectRel(object):
(x._get_pk_val(), smart_text(x)) for x in self.related_model._default_manager.all()
]
def get_db_prep_lookup(self, lookup_type, value, connection, prepared=False):
# Defer to the actual field definition for db prep
return self.field.get_db_prep_lookup(lookup_type, value, connection=connection, prepared=prepared)
def is_hidden(self):
"Should the related object be hidden?"
return bool(self.related_name) and self.related_name[-1] == '+'

View File

@@ -16,6 +16,7 @@ from django.utils.six.moves import range
class Lookup(object):
lookup_name = None
prepare_rhs = True
def __init__(self, lhs, rhs):
self.lhs, self.rhs = lhs, rhs
@@ -56,12 +57,14 @@ class Lookup(object):
return sqls, sqls_params
def get_prep_lookup(self):
return self.lhs.output_field.get_prep_lookup(self.lookup_name, self.rhs)
if hasattr(self.rhs, '_prepare'):
return self.rhs._prepare(self.lhs.output_field)
if self.prepare_rhs and hasattr(self.lhs.output_field, 'get_prep_value'):
return self.lhs.output_field.get_prep_value(self.rhs)
return self.rhs
def get_db_prep_lookup(self, value, connection):
return (
'%s', self.lhs.output_field.get_db_prep_lookup(
self.lookup_name, value, connection, prepared=True))
return ('%s', [value])
def process_lhs(self, compiler, connection, lhs=None):
lhs = lhs or self.lhs
@@ -199,6 +202,7 @@ Field.register_lookup(Exact)
class IExact(BuiltinLookup):
lookup_name = 'iexact'
prepare_rhs = False
def process_rhs(self, qn, connection):
rhs, params = super(IExact, self).process_rhs(qn, connection)
@@ -254,6 +258,13 @@ IntegerField.register_lookup(IntegerLessThan)
class In(FieldGetDbPrepValueIterableMixin, BuiltinLookup):
lookup_name = 'in'
def get_prep_lookup(self):
if hasattr(self.rhs, '_prepare'):
return self.rhs._prepare(self.lhs.output_field)
if hasattr(self.lhs.output_field, 'get_prep_value'):
return [self.lhs.output_field.get_prep_value(v) for v in self.rhs]
return self.rhs
def process_rhs(self, compiler, connection):
db_rhs = getattr(self.rhs, '_db', None)
if db_rhs is not None and db_rhs != connection.alias:
@@ -335,6 +346,7 @@ class PatternLookup(BuiltinLookup):
class Contains(PatternLookup):
lookup_name = 'contains'
prepare_rhs = False
def process_rhs(self, qn, connection):
rhs, params = super(Contains, self).process_rhs(qn, connection)
@@ -346,11 +358,13 @@ Field.register_lookup(Contains)
class IContains(Contains):
lookup_name = 'icontains'
prepare_rhs = False
Field.register_lookup(IContains)
class StartsWith(PatternLookup):
lookup_name = 'startswith'
prepare_rhs = False
def process_rhs(self, qn, connection):
rhs, params = super(StartsWith, self).process_rhs(qn, connection)
@@ -362,6 +376,7 @@ Field.register_lookup(StartsWith)
class IStartsWith(PatternLookup):
lookup_name = 'istartswith'
prepare_rhs = False
def process_rhs(self, qn, connection):
rhs, params = super(IStartsWith, self).process_rhs(qn, connection)
@@ -373,6 +388,7 @@ Field.register_lookup(IStartsWith)
class EndsWith(PatternLookup):
lookup_name = 'endswith'
prepare_rhs = False
def process_rhs(self, qn, connection):
rhs, params = super(EndsWith, self).process_rhs(qn, connection)
@@ -384,6 +400,7 @@ Field.register_lookup(EndsWith)
class IEndsWith(PatternLookup):
lookup_name = 'iendswith'
prepare_rhs = False
def process_rhs(self, qn, connection):
rhs, params = super(IEndsWith, self).process_rhs(qn, connection)
@@ -396,6 +413,11 @@ Field.register_lookup(IEndsWith)
class Range(FieldGetDbPrepValueIterableMixin, BuiltinLookup):
lookup_name = 'range'
def get_prep_lookup(self):
if hasattr(self.rhs, '_prepare'):
return self.rhs._prepare(self.lhs.output_field)
return [self.lhs.output_field.get_prep_value(v) for v in self.rhs]
def get_rhs_op(self, connection, rhs):
return "BETWEEN %s AND %s" % (rhs[0], rhs[1])
@@ -411,6 +433,7 @@ Field.register_lookup(Range)
class IsNull(BuiltinLookup):
lookup_name = 'isnull'
prepare_rhs = False
def as_sql(self, compiler, connection):
sql, params = compiler.compile(self.lhs)
@@ -423,6 +446,7 @@ Field.register_lookup(IsNull)
class Search(BuiltinLookup):
lookup_name = 'search'
prepare_rhs = False
def as_sql(self, compiler, connection):
warnings.warn(
@@ -438,6 +462,7 @@ Field.register_lookup(Search)
class Regex(BuiltinLookup):
lookup_name = 'regex'
prepare_rhs = False
def as_sql(self, compiler, connection):
if self.lookup_name in connection.operators: