Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
D
django
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
django
Commits
388bb5bd
Kaydet (Commit)
388bb5bd
authored
Nis 23, 2016
tarafından
Claude Paroz
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Fixed #22936 -- Obsoleted Field.get_prep_lookup()/get_db_prep_lookup()
Thanks Tim Graham for completing the initial patch.
üst
1206eea1
Hide whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
89 additions
and
220 deletions
+89
-220
filters.py
django/contrib/admin/filters.py
+3
-0
widgets.py
django/contrib/admin/widgets.py
+0
-1
fields.py
django/contrib/gis/db/models/fields.py
+0
-7
jsonb.py
django/contrib/postgres/fields/jsonb.py
+0
-7
ranges.py
django/contrib/postgres/fields/ranges.py
+1
-1
lookups.py
django/contrib/postgres/lookups.py
+6
-1
expressions.py
django/db/models/expressions.py
+1
-1
__init__.py
django/db/models/fields/__init__.py
+3
-55
files.py
django/db/models/fields/files.py
+0
-5
related_lookups.py
django/db/models/fields/related_lookups.py
+7
-7
reverse_related.py
django/db/models/fields/reverse_related.py
+0
-7
lookups.py
django/db/models/lookups.py
+29
-4
custom-model-fields.txt
docs/howto/custom-model-fields.txt
+0
-61
fields.txt
docs/ref/models/fields.txt
+1
-22
1.10.txt
docs/releases/1.10.txt
+19
-0
test_booleanfield.py
tests/model_fields/test_booleanfield.py
+13
-13
test_custom_fields.py
tests/model_fields/test_custom_fields.py
+0
-22
test_decimalfield.py
tests/model_fields/test_decimalfield.py
+4
-3
tests.py
tests/queries/tests.py
+2
-3
No files found.
django/contrib/admin/filters.py
Dosyayı görüntüle @
388bb5bd
...
...
@@ -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
]
...
...
django/contrib/admin/widgets.py
Dosyayı görüntüle @
388bb5bd
...
...
@@ -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
)
...
...
django/contrib/gis/db/models/fields.py
Dosyayı görüntüle @
388bb5bd
...
...
@@ -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
:
...
...
django/contrib/postgres/fields/jsonb.py
Dosyayı görüntüle @
388bb5bd
...
...
@@ -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
:
...
...
django/contrib/postgres/fields/ranges.py
Dosyayı görüntüle @
388bb5bd
...
...
@@ -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
)
...
...
django/contrib/postgres/lookups.py
Dosyayı görüntüle @
388bb5bd
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
=
'?|'
...
...
django/db/models/expressions.py
Dosyayı görüntüle @
388bb5bd
...
...
@@ -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
...
...
django/db/models/fields/__init__.py
Dosyayı görüntüle @
388bb5bd
...
...
@@ -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
=
{
...
...
django/db/models/fields/files.py
Dosyayı görüntüle @
388bb5bd
...
...
@@ -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
)
...
...
django/db/models/fields/related_lookups.py
Dosyayı görüntüle @
388bb5bd
...
...
@@ -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
()
...
...
django/db/models/fields/reverse_related.py
Dosyayı görüntüle @
388bb5bd
...
...
@@ -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
]
==
'+'
...
...
django/db/models/lookups.py
Dosyayı görüntüle @
388bb5bd
...
...
@@ -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
:
...
...
docs/howto/custom-model-fields.txt
Dosyayı görüntüle @
388bb5bd
...
...
@@ -577,67 +577,6 @@ the end. You should also update the model's attribute if you make any changes
to the value so that code holding references to the model will always see the
correct value.
.. _preparing-values-for-use-in-database-lookups:
Preparing values for use in database lookups
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
As with value conversions, preparing a value for database lookups is a
two phase process.
:meth:`.get_prep_lookup` performs the first phase of lookup preparation:
type conversion and data validation.
Prepares the ``value`` for passing to the database when used in a lookup (a
``WHERE`` constraint in SQL). The ``lookup_type`` parameter will be one of the
valid Django filter lookups: ``exact``, ``iexact``, ``contains``, ``icontains``,
``gt``, ``gte``, ``lt``, ``lte``, ``in``, ``startswith``, ``istartswith``,
``endswith``, ``iendswith``, ``range``, ``year``, ``month``, ``day``,
``isnull``, ``search``, ``regex``, and ``iregex``.
If you are using :doc:`custom lookups </howto/custom-lookups>`, the
``lookup_type`` can be any ``lookup_name`` used by the project's custom lookups.
Your method must be prepared to handle all of these ``lookup_type`` values and
should raise either a ``ValueError`` if the ``value`` is of the wrong sort (a
list when you were expecting an object, for example) or a ``TypeError`` if
your field does not support that type of lookup. For many fields, you can get
by with handling the lookup types that need special handling for your field
and pass the rest to the :meth:`~Field.get_db_prep_lookup` method of the parent
class.
If you needed to implement :meth:`.get_db_prep_save`, you will usually need to
implement :meth:`.get_prep_lookup`. If you don't, :meth:`.get_prep_value` will
be called by the default implementation, to manage ``exact``, ``gt``, ``gte``,
``lt``, ``lte``, ``in`` and ``range`` lookups.
You may also want to implement this method to limit the lookup types that could
be used with your custom field type.
Note that, for ``"range"`` and ``"in"`` lookups, ``get_prep_lookup`` will receive
a list of objects (presumably of the right type) and will need to convert them
to a list of things of the right type for passing to the database. Most of the
time, you can reuse ``get_prep_value()``, or at least factor out some common
pieces.
For example, the following code implements ``get_prep_lookup`` to limit the
accepted lookup types to ``exact`` and ``in``::
class HandField(models.Field):
# ...
def get_prep_lookup(self, lookup_type, value):
# We only handle 'exact' and 'in'. All others are errors.
if lookup_type == 'exact':
return self.get_prep_value(value)
elif lookup_type == 'in':
return [self.get_prep_value(v) for v in value]
else:
raise TypeError('Lookup type %r not supported.' % lookup_type)
For performing database-specific data conversions required by a lookup,
you can override :meth:`~Field.get_db_prep_lookup`.
.. _specifying-form-field-for-model-field:
Specifying the form field for a model field
...
...
docs/ref/models/fields.txt
Dosyayı görüntüle @
388bb5bd
...
...
@@ -1717,8 +1717,7 @@ Field API reference
``Field`` is an abstract class that represents a database table column.
Django uses fields to create the database table (:meth:`db_type`), to map
Python types to database (:meth:`get_prep_value`) and vice-versa
(:meth:`from_db_value`), and to apply :doc:`/ref/models/lookups`
(:meth:`get_prep_lookup`).
(:meth:`from_db_value`).
A field is thus a fundamental piece in different Django APIs, notably,
:class:`models <django.db.models.Model>` and :class:`querysets
...
...
@@ -1847,26 +1846,6 @@ Field API reference
See :ref:`preprocessing-values-before-saving` for usage.
When a lookup is used on a field, the value may need to be "prepared".
Django exposes two methods for this:
.. method:: get_prep_lookup(lookup_type, value)
Prepares ``value`` to the database prior to be used in a lookup.
The ``lookup_type`` will be the registered name of the lookup. For
example: ``"exact"``, ``"iexact"``, or ``"contains"``.
See :ref:`preparing-values-for-use-in-database-lookups` for usage.
.. method:: get_db_prep_lookup(lookup_type, value, connection, prepared=False)
Similar to :meth:`get_db_prep_value`, but for performing a lookup.
As with :meth:`get_db_prep_value`, the specific connection that will
be used for the query is passed as ``connection``. In addition,
``prepared`` describes whether the value has already been prepared with
:meth:`get_prep_lookup`.
Fields often receive their values as a different type, either from
serialization or from forms.
...
...
docs/releases/1.10.txt
Dosyayı görüntüle @
388bb5bd
...
...
@@ -677,6 +677,25 @@ You can check if your database has any of the removed hashers like this::
# Unsalted MD5 passwords might not have an 'md5$$' prefix:
User.objects.filter(password__length=32)
``Field.get_prep_lookup()`` and ``Field.get_db_prep_lookup()`` methods are removed
----------------------------------------------------------------------------------
If you have a custom field that implements either of these methods, register a
custom lookup for it. For example::
from django.db.models import Field
from django.db.models.lookups import Exact
class MyField(Field):
...
class MyFieldExact(Exact):
def get_prep_lookup(self):
# do_custom_stuff_for_myfield
....
MyField.register_lookup(MyFieldExact)
:mod:`django.contrib.gis`
-------------------------
...
...
tests/model_fields/test_booleanfield.py
Dosyayı görüntüle @
388bb5bd
from
django.core.exceptions
import
ValidationError
from
django.db
import
IntegrityError
,
connection
,
models
,
transaction
from
django.db
import
IntegrityError
,
models
,
transaction
from
django.test
import
SimpleTestCase
,
TestCase
from
.models
import
BooleanModel
,
FksToBooleans
,
NullBooleanModel
class
BooleanFieldTests
(
TestCase
):
def
_test_get_
db_prep_lookup
(
self
,
f
):
self
.
assertEqual
(
f
.
get_
db_prep_lookup
(
'exact'
,
True
,
connection
=
connection
),
[
True
]
)
self
.
assertEqual
(
f
.
get_
db_prep_lookup
(
'exact'
,
'1'
,
connection
=
connection
),
[
True
]
)
self
.
assertEqual
(
f
.
get_
db_prep_lookup
(
'exact'
,
1
,
connection
=
connection
),
[
True
]
)
self
.
assertEqual
(
f
.
get_
db_prep_lookup
(
'exact'
,
False
,
connection
=
connection
),
[
False
]
)
self
.
assertEqual
(
f
.
get_
db_prep_lookup
(
'exact'
,
'0'
,
connection
=
connection
),
[
False
]
)
self
.
assertEqual
(
f
.
get_
db_prep_lookup
(
'exact'
,
0
,
connection
=
connection
),
[
False
]
)
self
.
assertEqual
(
f
.
get_
db_prep_lookup
(
'exact'
,
None
,
connection
=
connection
),
[
None
]
)
def
_test_get_
prep_value
(
self
,
f
):
self
.
assertEqual
(
f
.
get_
prep_value
(
True
),
True
)
self
.
assertEqual
(
f
.
get_
prep_value
(
'1'
),
True
)
self
.
assertEqual
(
f
.
get_
prep_value
(
1
),
True
)
self
.
assertEqual
(
f
.
get_
prep_value
(
False
),
False
)
self
.
assertEqual
(
f
.
get_
prep_value
(
'0'
),
False
)
self
.
assertEqual
(
f
.
get_
prep_value
(
0
),
False
)
self
.
assertEqual
(
f
.
get_
prep_value
(
None
),
None
)
def
_test_to_python
(
self
,
f
):
self
.
assertIs
(
f
.
to_python
(
1
),
True
)
self
.
assertIs
(
f
.
to_python
(
0
),
False
)
def
test_booleanfield_get_
db_prep_lookup
(
self
):
self
.
_test_get_
db_prep_lookup
(
models
.
BooleanField
())
def
test_booleanfield_get_
prep_value
(
self
):
self
.
_test_get_
prep_value
(
models
.
BooleanField
())
def
test_nullbooleanfield_get_
db_prep_lookup
(
self
):
self
.
_test_get_
db_prep_lookup
(
models
.
NullBooleanField
())
def
test_nullbooleanfield_get_
prep_value
(
self
):
self
.
_test_get_
prep_value
(
models
.
NullBooleanField
())
def
test_booleanfield_to_python
(
self
):
self
.
_test_to_python
(
models
.
BooleanField
())
...
...
tests/model_fields/test_custom_fields.py
deleted
100644 → 0
Dosyayı görüntüle @
1206eea1
from
django.db
import
connection
,
models
from
django.test
import
SimpleTestCase
class
CustomFieldTests
(
SimpleTestCase
):
def
test_get_prep_value_count
(
self
):
"""
Field values are not prepared twice in get_db_prep_lookup() (#14786).
"""
class
NoopField
(
models
.
TextField
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
self
.
prep_value_count
=
0
super
(
NoopField
,
self
)
.
__init__
(
*
args
,
**
kwargs
)
def
get_prep_value
(
self
,
value
):
self
.
prep_value_count
+=
1
return
super
(
NoopField
,
self
)
.
get_prep_value
(
value
)
field
=
NoopField
()
field
.
get_db_prep_lookup
(
'exact'
,
'TEST'
,
connection
=
connection
,
prepared
=
False
)
self
.
assertEqual
(
field
.
prep_value_count
,
1
)
tests/model_fields/test_decimalfield.py
Dosyayı görüntüle @
388bb5bd
...
...
@@ -2,7 +2,7 @@ from decimal import Decimal
from
django.core
import
validators
from
django.core.exceptions
import
ValidationError
from
django.db
import
connection
,
models
from
django.db
import
models
from
django.test
import
TestCase
from
.models
import
BigD
,
Foo
...
...
@@ -27,9 +27,10 @@ class DecimalFieldTests(TestCase):
self
.
assertEqual
(
f
.
_format
(
f
.
to_python
(
'2.6'
)),
'2.6'
)
self
.
assertEqual
(
f
.
_format
(
None
),
None
)
def
test_get_
db_prep_lookup
(
self
):
def
test_get_
prep_value
(
self
):
f
=
models
.
DecimalField
(
max_digits
=
5
,
decimal_places
=
1
)
self
.
assertEqual
(
f
.
get_db_prep_lookup
(
'exact'
,
None
,
connection
=
connection
),
[
None
])
self
.
assertEqual
(
f
.
get_prep_value
(
None
),
None
)
self
.
assertEqual
(
f
.
get_prep_value
(
'2.4'
),
Decimal
(
'2.4'
))
def
test_filter_with_strings
(
self
):
"""
...
...
tests/queries/tests.py
Dosyayı görüntüle @
388bb5bd
...
...
@@ -1229,9 +1229,8 @@ class Queries2Tests(TestCase):
)
def
test_ticket12239
(
self
):
# Float was being rounded to integer on gte queries on integer field. Tests
# show that gt, lt, gte, and lte work as desired. Note that the fix changes
# get_prep_lookup for gte and lt queries only.
# Custom lookups are registered to round float values correctly on gte
# and lt IntegerField queries.
self
.
assertQuerysetEqual
(
Number
.
objects
.
filter
(
num__gt
=
11.9
),
[
'<Number: 12>'
]
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment