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
b5e0eede
Kaydet (Commit)
b5e0eede
authored
Mar 22, 2015
tarafından
Jon Dufresne
Kaydeden (comit)
Tim Graham
Nis 20, 2015
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Fixed #22394 -- Refactored built-in datetime lookups to transforms.
üst
039d7881
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
251 additions
and
109 deletions
+251
-109
AUTHORS
AUTHORS
+1
-0
__init__.py
django/db/models/fields/__init__.py
+142
-24
lookups.py
django/db/models/lookups.py
+0
-58
querysets.txt
docs/ref/models/querysets.txt
+55
-8
1.9.txt
docs/releases/1.9.txt
+4
-0
tests.py
tests/custom_lookups/tests.py
+21
-19
tests.py
tests/lookup/tests.py
+28
-0
No files found.
AUTHORS
Dosyayı görüntüle @
b5e0eede
...
...
@@ -347,6 +347,7 @@ answer newbie questions, and generally made Django that much better:
John Paulett <john@paulett.org>
John Shaffer <jshaffer2112@gmail.com>
Jökull Sólberg Auðunsson <jokullsolberg@gmail.com>
Jon Dufresne <jon.dufresne@gmail.com>
Jonathan Buchanan <jonathan.buchanan@gmail.com>
Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/>
Jonathan Feignberg <jdf@pobox.com>
...
...
django/db/models/fields/__init__.py
Dosyayı görüntüle @
b5e0eede
...
...
@@ -12,7 +12,7 @@ from base64 import b64decode, b64encode
from
django.apps
import
apps
from
django.db
import
connection
from
django.db.models.lookups
import
default_lookups
,
RegisterLookupMixin
from
django.db.models.lookups
import
default_lookups
,
RegisterLookupMixin
,
Transform
,
Lookup
from
django.db.models.query_utils
import
QueryWrapper
from
django.conf
import
settings
from
django
import
forms
...
...
@@ -724,7 +724,6 @@ class Field(RegisterLookupMixin):
if
lookup_type
in
{
'iexact'
,
'contains'
,
'icontains'
,
'startswith'
,
'istartswith'
,
'endswith'
,
'iendswith'
,
'month'
,
'day'
,
'week_day'
,
'hour'
,
'minute'
,
'second'
,
'isnull'
,
'search'
,
'regex'
,
'iregex'
,
}:
return
value
...
...
@@ -732,12 +731,6 @@ class Field(RegisterLookupMixin):
return
self
.
get_prep_value
(
value
)
elif
lookup_type
in
(
'range'
,
'in'
):
return
[
self
.
get_prep_value
(
v
)
for
v
in
value
]
elif
lookup_type
==
'year'
:
try
:
return
int
(
value
)
except
ValueError
:
raise
ValueError
(
"The __year lookup type requires an integer "
"argument"
)
return
self
.
get_prep_value
(
value
)
def
get_db_prep_lookup
(
self
,
lookup_type
,
value
,
connection
,
...
...
@@ -761,8 +754,7 @@ class Field(RegisterLookupMixin):
sql
,
params
=
value
.
_as_sql
(
connection
=
connection
)
return
QueryWrapper
((
'(
%
s)'
%
sql
),
params
)
if
lookup_type
in
(
'month'
,
'day'
,
'week_day'
,
'hour'
,
'minute'
,
'second'
,
'search'
,
'regex'
,
'iregex'
,
'contains'
,
if
lookup_type
in
(
'search'
,
'regex'
,
'iregex'
,
'contains'
,
'icontains'
,
'iexact'
,
'startswith'
,
'endswith'
,
'istartswith'
,
'iendswith'
):
return
[
value
]
...
...
@@ -774,13 +766,6 @@ class Field(RegisterLookupMixin):
prepared
=
prepared
)
for
v
in
value
]
elif
lookup_type
==
'isnull'
:
return
[]
elif
lookup_type
==
'year'
:
if
isinstance
(
self
,
DateTimeField
):
return
connection
.
ops
.
year_lookup_bounds_for_datetime_field
(
value
)
elif
isinstance
(
self
,
DateField
):
return
connection
.
ops
.
year_lookup_bounds_for_date_field
(
value
)
else
:
return
[
value
]
# this isn't supposed to happen
else
:
return
[
value
]
...
...
@@ -1302,13 +1287,6 @@ class DateField(DateTimeCheckMixin, Field):
curry
(
cls
.
_get_next_or_previous_by_FIELD
,
field
=
self
,
is_next
=
False
))
def
get_prep_lookup
(
self
,
lookup_type
,
value
):
# For dates lookups, convert the value to an int
# so the database backend always sees a consistent type.
if
lookup_type
in
(
'month'
,
'day'
,
'week_day'
,
'hour'
,
'minute'
,
'second'
):
return
int
(
value
)
return
super
(
DateField
,
self
)
.
get_prep_lookup
(
lookup_type
,
value
)
def
get_prep_value
(
self
,
value
):
value
=
super
(
DateField
,
self
)
.
get_prep_value
(
value
)
return
self
.
to_python
(
value
)
...
...
@@ -2408,3 +2386,143 @@ class UUIDField(Field):
}
defaults
.
update
(
kwargs
)
return
super
(
UUIDField
,
self
)
.
formfield
(
**
defaults
)
class
DateTransform
(
Transform
):
def
as_sql
(
self
,
compiler
,
connection
):
sql
,
params
=
compiler
.
compile
(
self
.
lhs
)
lhs_output_field
=
self
.
lhs
.
output_field
if
isinstance
(
lhs_output_field
,
DateTimeField
):
tzname
=
timezone
.
get_current_timezone_name
()
if
settings
.
USE_TZ
else
None
sql
,
tz_params
=
connection
.
ops
.
datetime_extract_sql
(
self
.
lookup_name
,
sql
,
tzname
)
params
.
extend
(
tz_params
)
else
:
# DateField and TimeField.
sql
=
connection
.
ops
.
date_extract_sql
(
self
.
lookup_name
,
sql
)
return
sql
,
params
@cached_property
def
output_field
(
self
):
return
IntegerField
()
class
YearTransform
(
DateTransform
):
lookup_name
=
'year'
class
YearLookup
(
Lookup
):
def
year_lookup_bounds
(
self
,
connection
,
year
):
output_field
=
self
.
lhs
.
lhs
.
output_field
if
isinstance
(
output_field
,
DateTimeField
):
bounds
=
connection
.
ops
.
year_lookup_bounds_for_datetime_field
(
year
)
else
:
bounds
=
connection
.
ops
.
year_lookup_bounds_for_date_field
(
year
)
return
bounds
@YearTransform.register_lookup
class
YearExact
(
YearLookup
):
lookup_name
=
'exact'
def
as_sql
(
self
,
compiler
,
connection
):
# We will need to skip the extract part and instead go
# directly with the originating field, that is self.lhs.lhs.
lhs_sql
,
params
=
self
.
process_lhs
(
compiler
,
connection
,
self
.
lhs
.
lhs
)
rhs_sql
,
rhs_params
=
self
.
process_rhs
(
compiler
,
connection
)
bounds
=
self
.
year_lookup_bounds
(
connection
,
rhs_params
[
0
])
params
.
extend
(
bounds
)
return
'
%
s BETWEEN
%%
s AND
%%
s'
%
lhs_sql
,
params
class
YearComparisonLookup
(
YearLookup
):
def
as_sql
(
self
,
compiler
,
connection
):
# We will need to skip the extract part and instead go
# directly with the originating field, that is self.lhs.lhs.
lhs_sql
,
params
=
self
.
process_lhs
(
compiler
,
connection
,
self
.
lhs
.
lhs
)
rhs_sql
,
rhs_params
=
self
.
process_rhs
(
compiler
,
connection
)
rhs_sql
=
self
.
get_rhs_op
(
connection
,
rhs_sql
)
start
,
finish
=
self
.
year_lookup_bounds
(
connection
,
rhs_params
[
0
])
params
.
append
(
self
.
get_bound
(
start
,
finish
))
return
'
%
s
%
s'
%
(
lhs_sql
,
rhs_sql
),
params
def
get_rhs_op
(
self
,
connection
,
rhs
):
return
connection
.
operators
[
self
.
lookup_name
]
%
rhs
def
get_bound
(
self
):
raise
NotImplementedError
(
'subclasses of YearComparisonLookup must provide a get_bound() method'
)
@YearTransform.register_lookup
class
YearGt
(
YearComparisonLookup
):
lookup_name
=
'gt'
def
get_bound
(
self
,
start
,
finish
):
return
finish
@YearTransform.register_lookup
class
YearGte
(
YearComparisonLookup
):
lookup_name
=
'gte'
def
get_bound
(
self
,
start
,
finish
):
return
start
@YearTransform.register_lookup
class
YearLt
(
YearComparisonLookup
):
lookup_name
=
'lt'
def
get_bound
(
self
,
start
,
finish
):
return
start
@YearTransform.register_lookup
class
YearLte
(
YearComparisonLookup
):
lookup_name
=
'lte'
def
get_bound
(
self
,
start
,
finish
):
return
finish
class
MonthTransform
(
DateTransform
):
lookup_name
=
'month'
class
DayTransform
(
DateTransform
):
lookup_name
=
'day'
class
WeekDayTransform
(
DateTransform
):
lookup_name
=
'week_day'
class
HourTransform
(
DateTransform
):
lookup_name
=
'hour'
class
MinuteTransform
(
DateTransform
):
lookup_name
=
'minute'
class
SecondTransform
(
DateTransform
):
lookup_name
=
'second'
DateField
.
register_lookup
(
YearTransform
)
DateField
.
register_lookup
(
MonthTransform
)
DateField
.
register_lookup
(
DayTransform
)
DateField
.
register_lookup
(
WeekDayTransform
)
TimeField
.
register_lookup
(
HourTransform
)
TimeField
.
register_lookup
(
MinuteTransform
)
TimeField
.
register_lookup
(
SecondTransform
)
DateTimeField
.
register_lookup
(
YearTransform
)
DateTimeField
.
register_lookup
(
MonthTransform
)
DateTimeField
.
register_lookup
(
DayTransform
)
DateTimeField
.
register_lookup
(
WeekDayTransform
)
DateTimeField
.
register_lookup
(
HourTransform
)
DateTimeField
.
register_lookup
(
MinuteTransform
)
DateTimeField
.
register_lookup
(
SecondTransform
)
django/db/models/lookups.py
Dosyayı görüntüle @
b5e0eede
import
inspect
from
copy
import
copy
from
django.conf
import
settings
from
django.utils
import
timezone
from
django.utils.functional
import
cached_property
from
django.utils.six.moves
import
range
...
...
@@ -408,11 +406,6 @@ class Between(BuiltinLookup):
return
"BETWEEN
%
s AND
%
s"
%
(
rhs
,
rhs
)
class
Year
(
Between
):
lookup_name
=
'year'
default_lookups
[
'year'
]
=
Year
class
Range
(
BuiltinLookup
):
lookup_name
=
'range'
...
...
@@ -430,57 +423,6 @@ class Range(BuiltinLookup):
default_lookups
[
'range'
]
=
Range
class
DateLookup
(
BuiltinLookup
):
def
process_lhs
(
self
,
compiler
,
connection
,
lhs
=
None
):
from
django.db.models
import
DateTimeField
lhs
,
params
=
super
(
DateLookup
,
self
)
.
process_lhs
(
compiler
,
connection
,
lhs
)
if
isinstance
(
self
.
lhs
.
output_field
,
DateTimeField
):
tzname
=
timezone
.
get_current_timezone_name
()
if
settings
.
USE_TZ
else
None
sql
,
tz_params
=
connection
.
ops
.
datetime_extract_sql
(
self
.
extract_type
,
lhs
,
tzname
)
return
connection
.
ops
.
lookup_cast
(
self
.
lookup_name
)
%
sql
,
tz_params
else
:
return
connection
.
ops
.
date_extract_sql
(
self
.
lookup_name
,
lhs
),
[]
def
get_rhs_op
(
self
,
connection
,
rhs
):
return
'=
%
s'
%
rhs
class
Month
(
DateLookup
):
lookup_name
=
'month'
extract_type
=
'month'
default_lookups
[
'month'
]
=
Month
class
Day
(
DateLookup
):
lookup_name
=
'day'
extract_type
=
'day'
default_lookups
[
'day'
]
=
Day
class
WeekDay
(
DateLookup
):
lookup_name
=
'week_day'
extract_type
=
'week_day'
default_lookups
[
'week_day'
]
=
WeekDay
class
Hour
(
DateLookup
):
lookup_name
=
'hour'
extract_type
=
'hour'
default_lookups
[
'hour'
]
=
Hour
class
Minute
(
DateLookup
):
lookup_name
=
'minute'
extract_type
=
'minute'
default_lookups
[
'minute'
]
=
Minute
class
Second
(
DateLookup
):
lookup_name
=
'second'
extract_type
=
'second'
default_lookups
[
'second'
]
=
Second
class
IsNull
(
BuiltinLookup
):
lookup_name
=
'isnull'
...
...
docs/ref/models/querysets.txt
Dosyayı görüntüle @
b5e0eede
...
...
@@ -2431,36 +2431,45 @@ numbers and even characters.
year
~~~~
For date and datetime fields, an exact year match. Takes an integer year.
For date and datetime fields, an exact year match. Allows chaining additional
field lookups. Takes an integer year.
Example::
Entry.objects.filter(pub_date__year=2005)
Entry.objects.filter(pub_date__year__gte=2005)
SQL equivalent::
SELECT ... WHERE pub_date BETWEEN '2005-01-01' AND '2005-12-31';
SELECT ... WHERE pub_date >= '2005-01-01';
(The exact SQL syntax varies for each database engine.)
When :setting:`USE_TZ` is ``True``, datetime fields are converted to the
current time zone before filtering.
.. versionchanged:: 1.9
Allowed chaining additional field lookups.
.. fieldlookup:: month
month
~~~~~
For date and datetime fields, an exact month match.
Takes an integer 1
(January) through 12 (December).
For date and datetime fields, an exact month match.
Allows chaining additional
field lookups. Takes an integer 1
(January) through 12 (December).
Example::
Entry.objects.filter(pub_date__month=12)
Entry.objects.filter(pub_date__month__gte=6)
SQL equivalent::
SELECT ... WHERE EXTRACT('month' FROM pub_date) = '12';
SELECT ... WHERE EXTRACT('month' FROM pub_date) >= '6';
(The exact SQL syntax varies for each database engine.)
...
...
@@ -2468,20 +2477,27 @@ When :setting:`USE_TZ` is ``True``, datetime fields are converted to the
current time zone before filtering. This requires :ref:`time zone definitions
in the database <database-time-zone-definitions>`.
.. versionchanged:: 1.9
Allowed chaining additional field lookups.
.. fieldlookup:: day
day
~~~
For date and datetime fields, an exact day match. Takes an integer day.
For date and datetime fields, an exact day match. Allows chaining additional
field lookups. Takes an integer day.
Example::
Entry.objects.filter(pub_date__day=3)
Entry.objects.filter(pub_date__day__gte=3)
SQL equivalent::
SELECT ... WHERE EXTRACT('day' FROM pub_date) = '3';
SELECT ... WHERE EXTRACT('day' FROM pub_date) >= '3';
(The exact SQL syntax varies for each database engine.)
...
...
@@ -2492,12 +2508,17 @@ When :setting:`USE_TZ` is ``True``, datetime fields are converted to the
current time zone before filtering. This requires :ref:`time zone definitions
in the database <database-time-zone-definitions>`.
.. versionchanged:: 1.9
Allowed chaining additional field lookups.
.. fieldlookup:: week_day
week_day
~~~~~~~~
For date and datetime fields, a 'day of the week' match.
For date and datetime fields, a 'day of the week' match. Allows chaining
additional field lookups.
Takes an integer value representing the day of week from 1 (Sunday) to 7
(Saturday).
...
...
@@ -2505,6 +2526,7 @@ Takes an integer value representing the day of week from 1 (Sunday) to 7
Example::
Entry.objects.filter(pub_date__week_day=2)
Entry.objects.filter(pub_date__week_day__gte=2)
(No equivalent SQL code fragment is included for this lookup because
implementation of the relevant query varies among different database engines.)
...
...
@@ -2517,66 +2539,91 @@ When :setting:`USE_TZ` is ``True``, datetime fields are converted to the
current time zone before filtering. This requires :ref:`time zone definitions
in the database <database-time-zone-definitions>`.
.. versionchanged:: 1.9
Allowed chaining additional field lookups.
.. fieldlookup:: hour
hour
~~~~
For datetime fields, an exact hour match. Takes an integer between 0 and 23.
For datetime fields, an exact hour match. Allows chaining additional field
lookups. Takes an integer between 0 and 23.
Example::
Event.objects.filter(timestamp__hour=23)
Event.objects.filter(timestamp__hour__gte=12)
SQL equivalent::
SELECT ... WHERE EXTRACT('hour' FROM timestamp) = '23';
SELECT ... WHERE EXTRACT('hour' FROM timestamp) >= '12';
(The exact SQL syntax varies for each database engine.)
When :setting:`USE_TZ` is ``True``, values are converted to the current time
zone before filtering.
.. versionchanged:: 1.9
Allowed chaining additional field lookups.
.. fieldlookup:: minute
minute
~~~~~~
For datetime fields, an exact minute match. Takes an integer between 0 and 59.
For datetime fields, an exact minute match. Allows chaining additional field
lookups. Takes an integer between 0 and 59.
Example::
Event.objects.filter(timestamp__minute=29)
Event.objects.filter(timestamp__minute__gte=29)
SQL equivalent::
SELECT ... WHERE EXTRACT('minute' FROM timestamp) = '29';
SELECT ... WHERE EXTRACT('minute' FROM timestamp) >= '29';
(The exact SQL syntax varies for each database engine.)
When :setting:`USE_TZ` is ``True``, values are converted to the current time
zone before filtering.
.. versionchanged:: 1.9
Allowed chaining additional field lookups.
.. fieldlookup:: second
second
~~~~~~
For datetime fields, an exact second match. Takes an integer between 0 and 59.
For datetime fields, an exact second match. Allows chaining additional field
lookups. Takes an integer between 0 and 59.
Example::
Event.objects.filter(timestamp__second=31)
Event.objects.filter(timestamp__second__gte=31)
SQL equivalent::
SELECT ... WHERE EXTRACT('second' FROM timestamp) = '31';
SELECT ... WHERE EXTRACT('second' FROM timestamp) >= '31';
(The exact SQL syntax varies for each database engine.)
When :setting:`USE_TZ` is ``True``, values are converted to the current time
zone before filtering.
.. versionchanged:: 1.9
Allowed chaining additional field lookups.
.. fieldlookup:: isnull
isnull
...
...
docs/releases/1.9.txt
Dosyayı görüntüle @
b5e0eede
...
...
@@ -184,6 +184,10 @@ Models
* Added a system check to prevent defining both ``Meta.ordering`` and
``order_with_respect_to`` on the same model.
* :lookup:`Date and time <year>` lookups can be chained with other lookups
(such as :lookup:`exact`, :lookup:`gt`, :lookup:`lt`, etc.). For example:
``Entry.objects.filter(pub_date__month__gt=6)``.
CSRF
^^^^
...
...
tests/custom_lookups/tests.py
Dosyayı görüntüle @
b5e0eede
...
...
@@ -63,7 +63,8 @@ class UpperBilateralTransform(models.Transform):
class
YearTransform
(
models
.
Transform
):
lookup_name
=
'year'
# Use a name that avoids collision with the built-in year lookup.
lookup_name
=
'testyear'
def
as_sql
(
self
,
compiler
,
connection
):
lhs_sql
,
params
=
compiler
.
compile
(
self
.
lhs
)
...
...
@@ -400,19 +401,19 @@ class YearLteTests(TestCase):
def
test_year_lte
(
self
):
baseqs
=
Author
.
objects
.
order_by
(
'name'
)
self
.
assertQuerysetEqual
(
baseqs
.
filter
(
birthdate__year__lte
=
2012
),
baseqs
.
filter
(
birthdate__
test
year__lte
=
2012
),
[
self
.
a1
,
self
.
a2
,
self
.
a3
,
self
.
a4
],
lambda
x
:
x
)
self
.
assertQuerysetEqual
(
baseqs
.
filter
(
birthdate__year
=
2012
),
baseqs
.
filter
(
birthdate__
test
year
=
2012
),
[
self
.
a2
,
self
.
a3
,
self
.
a4
],
lambda
x
:
x
)
self
.
assertNotIn
(
'BETWEEN'
,
str
(
baseqs
.
filter
(
birthdate__year
=
2012
)
.
query
))
self
.
assertNotIn
(
'BETWEEN'
,
str
(
baseqs
.
filter
(
birthdate__
test
year
=
2012
)
.
query
))
self
.
assertQuerysetEqual
(
baseqs
.
filter
(
birthdate__year__lte
=
2011
),
baseqs
.
filter
(
birthdate__
test
year__lte
=
2011
),
[
self
.
a1
],
lambda
x
:
x
)
# The non-optimized version works, too.
self
.
assertQuerysetEqual
(
baseqs
.
filter
(
birthdate__year__lt
=
2012
),
baseqs
.
filter
(
birthdate__
test
year__lt
=
2012
),
[
self
.
a1
],
lambda
x
:
x
)
@unittest.skipUnless
(
connection
.
vendor
==
'postgresql'
,
"PostgreSQL specific SQL used"
)
...
...
@@ -425,10 +426,10 @@ class YearLteTests(TestCase):
self
.
a4
.
save
()
baseqs
=
Author
.
objects
.
order_by
(
'name'
)
self
.
assertQuerysetEqual
(
baseqs
.
filter
(
birthdate__year__lte
=
models
.
F
(
'age'
)),
baseqs
.
filter
(
birthdate__
test
year__lte
=
models
.
F
(
'age'
)),
[
self
.
a3
,
self
.
a4
],
lambda
x
:
x
)
self
.
assertQuerysetEqual
(
baseqs
.
filter
(
birthdate__year__lt
=
models
.
F
(
'age'
)),
baseqs
.
filter
(
birthdate__
test
year__lt
=
models
.
F
(
'age'
)),
[
self
.
a4
],
lambda
x
:
x
)
def
test_year_lte_sql
(
self
):
...
...
@@ -437,16 +438,16 @@ class YearLteTests(TestCase):
# error - not running YearLte SQL at all.
baseqs
=
Author
.
objects
.
order_by
(
'name'
)
self
.
assertIn
(
'<= (2011 || '
,
str
(
baseqs
.
filter
(
birthdate__year__lte
=
2011
)
.
query
))
'<= (2011 || '
,
str
(
baseqs
.
filter
(
birthdate__
test
year__lte
=
2011
)
.
query
))
self
.
assertIn
(
'-12-31'
,
str
(
baseqs
.
filter
(
birthdate__year__lte
=
2011
)
.
query
))
'-12-31'
,
str
(
baseqs
.
filter
(
birthdate__
test
year__lte
=
2011
)
.
query
))
def
test_postgres_year_exact
(
self
):
baseqs
=
Author
.
objects
.
order_by
(
'name'
)
self
.
assertIn
(
'= (2011 || '
,
str
(
baseqs
.
filter
(
birthdate__year
=
2011
)
.
query
))
'= (2011 || '
,
str
(
baseqs
.
filter
(
birthdate__
test
year
=
2011
)
.
query
))
self
.
assertIn
(
'-12-31'
,
str
(
baseqs
.
filter
(
birthdate__year
=
2011
)
.
query
))
'-12-31'
,
str
(
baseqs
.
filter
(
birthdate__
test
year
=
2011
)
.
query
))
def
test_custom_implementation_year_exact
(
self
):
try
:
...
...
@@ -462,7 +463,7 @@ class YearLteTests(TestCase):
setattr
(
YearExact
,
'as_'
+
connection
.
vendor
,
as_custom_sql
)
self
.
assertIn
(
'concat('
,
str
(
Author
.
objects
.
filter
(
birthdate__year
=
2012
)
.
query
))
str
(
Author
.
objects
.
filter
(
birthdate__
test
year
=
2012
)
.
query
))
finally
:
delattr
(
YearExact
,
'as_'
+
connection
.
vendor
)
try
:
...
...
@@ -483,14 +484,15 @@ class YearLteTests(TestCase):
YearTransform
.
register_lookup
(
CustomYearExact
)
self
.
assertIn
(
'CONCAT('
,
str
(
Author
.
objects
.
filter
(
birthdate__year
=
2012
)
.
query
))
str
(
Author
.
objects
.
filter
(
birthdate__
test
year
=
2012
)
.
query
))
finally
:
YearTransform
.
_unregister_lookup
(
CustomYearExact
)
YearTransform
.
register_lookup
(
YearExact
)
class
TrackCallsYearTransform
(
YearTransform
):
lookup_name
=
'year'
# Use a name that avoids collision with the built-in year lookup.
lookup_name
=
'testyear'
call_order
=
[]
def
as_sql
(
self
,
compiler
,
connection
):
...
...
@@ -516,23 +518,23 @@ class LookupTransformCallOrderTests(TestCase):
try
:
# junk lookup - tries lookup, then transform, then fails
with
self
.
assertRaises
(
FieldError
):
Author
.
objects
.
filter
(
birthdate__year__junk
=
2012
)
Author
.
objects
.
filter
(
birthdate__
test
year__junk
=
2012
)
self
.
assertEqual
(
TrackCallsYearTransform
.
call_order
,
[
'lookup'
,
'transform'
])
TrackCallsYearTransform
.
call_order
=
[]
# junk transform - tries transform only, then fails
with
self
.
assertRaises
(
FieldError
):
Author
.
objects
.
filter
(
birthdate__year__junk__more_junk
=
2012
)
Author
.
objects
.
filter
(
birthdate__
test
year__junk__more_junk
=
2012
)
self
.
assertEqual
(
TrackCallsYearTransform
.
call_order
,
[
'transform'
])
TrackCallsYearTransform
.
call_order
=
[]
# Just getting the year (implied __exact) - lookup only
Author
.
objects
.
filter
(
birthdate__year
=
2012
)
Author
.
objects
.
filter
(
birthdate__
test
year
=
2012
)
self
.
assertEqual
(
TrackCallsYearTransform
.
call_order
,
[
'lookup'
])
TrackCallsYearTransform
.
call_order
=
[]
# Just getting the year (explicit __exact) - lookup only
Author
.
objects
.
filter
(
birthdate__year__exact
=
2012
)
Author
.
objects
.
filter
(
birthdate__
test
year__exact
=
2012
)
self
.
assertEqual
(
TrackCallsYearTransform
.
call_order
,
[
'lookup'
])
...
...
tests/lookup/tests.py
Dosyayı görüntüle @
b5e0eede
...
...
@@ -713,6 +713,34 @@ class LookupTests(TestCase):
self
.
assertEqual
(
Player
.
objects
.
filter
(
games__season__year__gt
=
2010
)
.
distinct
()
.
count
(),
2
)
self
.
assertEqual
(
Player
.
objects
.
filter
(
games__season__gt__gt
=
222
)
.
distinct
()
.
count
(),
2
)
def
test_chain_date_time_lookups
(
self
):
self
.
assertQuerysetEqual
(
Article
.
objects
.
filter
(
pub_date__month__gt
=
7
),
[
'<Article: Article 5>'
,
'<Article: Article 6>'
],
ordered
=
False
)
self
.
assertQuerysetEqual
(
Article
.
objects
.
filter
(
pub_date__day__gte
=
27
),
[
'<Article: Article 2>'
,
'<Article: Article 3>'
,
'<Article: Article 4>'
,
'<Article: Article 7>'
],
ordered
=
False
)
self
.
assertQuerysetEqual
(
Article
.
objects
.
filter
(
pub_date__hour__lt
=
8
),
[
'<Article: Article 1>'
,
'<Article: Article 2>'
,
'<Article: Article 3>'
,
'<Article: Article 4>'
,
'<Article: Article 7>'
],
ordered
=
False
)
self
.
assertQuerysetEqual
(
Article
.
objects
.
filter
(
pub_date__minute__lte
=
0
),
[
'<Article: Article 1>'
,
'<Article: Article 2>'
,
'<Article: Article 3>'
,
'<Article: Article 4>'
,
'<Article: Article 5>'
,
'<Article: Article 6>'
,
'<Article: Article 7>'
],
ordered
=
False
)
class
LookupTransactionTests
(
TransactionTestCase
):
available_apps
=
[
'lookup'
]
...
...
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