Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b3b71a0

Browse files
committed
Fixed #7560 -- Moved a lot of the value conversion preparation for
loading/saving interactions with the databases into django.db.backend. This helps external db backend writers and removes a bunch of database-specific if-tests in django.db.models.fields. Great work from Leo Soto. git-svn-id: http://code.djangoproject.com/svn/django/trunk@8131 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent 7bc728c commit b3b71a0

File tree

11 files changed

+318
-135
lines changed

11 files changed

+318
-135
lines changed

‎django/db/backends/__init__.py‎

Lines changed: 66 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
# Import copy of _thread_local.py from Python 2.4
66
from django.utils._threading_local import local
77

8+
from django.db.backends import util
9+
from django.utils import datetime_safe
10+
811
class BaseDatabaseWrapper(local):
912
"""
1013
Represents a database connection.
@@ -36,23 +39,21 @@ def cursor(self):
3639
return cursor
3740

3841
def make_debug_cursor(self, cursor):
39-
from django.db.backends import util
4042
return util.CursorDebugWrapper(cursor, self)
4143

4244
class BaseDatabaseFeatures(object):
4345
allows_group_by_ordinal = True
4446
inline_fk_references = True
47+
# True if django.db.backend.utils.typecast_timestamp is used on values
48+
# returned from dates() calls.
4549
needs_datetime_string_cast = True
4650
supports_constraints = True
4751
supports_tablespaces = False
4852
uses_case_insensitive_names = False
4953
uses_custom_query_class = False
5054
empty_fetchmany_value = []
5155
update_can_self_select = True
52-
supports_usecs = True
53-
time_field_needs_date = False
5456
interprets_empty_strings_as_nulls = False
55-
date_field_supports_time_value = True
5657
can_use_chunked_reads = True
5758

5859
class BaseDatabaseOperations(object):
@@ -263,3 +264,64 @@ def prep_for_like_query(self, x):
263264
"""Prepares a value for use in a LIKE query."""
264265
from django.utils.encoding import smart_unicode
265266
return smart_unicode(x).replace("\\", "\\\\").replace("%", "\%").replace("_", "\_")
267+
268+
def value_to_db_date(self, value):
269+
"""
270+
Transform a date value to an object compatible with what is expected
271+
by the backend driver for date columns.
272+
"""
273+
if value is None:
274+
return None
275+
return datetime_safe.new_date(value).strftime('%Y-%m-%d')
276+
277+
def value_to_db_datetime(self, value):
278+
"""
279+
Transform a datetime value to an object compatible with what is expected
280+
by the backend driver for date columns.
281+
"""
282+
if value is None:
283+
return None
284+
return unicode(value)
285+
286+
def value_to_db_time(self, value):
287+
"""
288+
Transform a datetime value to an object compatible with what is expected
289+
by the backend driver for date columns.
290+
"""
291+
if value is None:
292+
return None
293+
return unicode(value)
294+
295+
def value_to_db_decimal(self, value, max_digits, decimal_places):
296+
"""
297+
Transform a decimal.Decimal value to an object compatible with what is
298+
expected by the backend driver for decimal (numeric) columns.
299+
"""
300+
if value is None:
301+
return None
302+
return util.format_number(value, max_digits, decimal_places)
303+
304+
def year_lookup_bounds(self, value):
305+
"""
306+
Returns a two-elements list with the lower and upper bound to be used
307+
with a BETWEEN operator to query a field value using a year lookup
308+
309+
`value` is an int, containing the looked-up year.
310+
"""
311+
first = '%s-01-01 00:00:00'
312+
second = '%s-12-31 23:59:59.999999'
313+
return [first % value, second % value]
314+
315+
def year_lookup_bounds_for_date_field(self, value):
316+
"""
317+
Returns a two-elements list with the lower and upper bound to be used
318+
with a BETWEEN operator to query a DateField value using a year lookup
319+
320+
`value` is an int, containing the looked-up year.
321+
322+
By default, it just calls `self.year_lookup_bounds`. Some backends need
323+
this hook because on their DB date fields can't be compared to values
324+
which include a time part.
325+
"""
326+
return self.year_lookup_bounds(value)
327+

‎django/db/backends/mysql/base.py‎

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ class DatabaseFeatures(BaseDatabaseFeatures):
6363
inline_fk_references = False
6464
empty_fetchmany_value = ()
6565
update_can_self_select = False
66-
supports_usecs = False
6766

6867
class DatabaseOperations(BaseDatabaseOperations):
6968
def date_extract_sql(self, lookup_type, field_name):
@@ -124,6 +123,24 @@ def sql_flush(self, style, tables, sequences):
124123
else:
125124
return []
126125

126+
def value_to_db_datetime(self, value):
127+
# MySQL doesn't support microseconds
128+
if value is None:
129+
return None
130+
return unicode(value.replace(microsecond=0))
131+
132+
def value_to_db_time(self, value):
133+
# MySQL doesn't support microseconds
134+
if value is None:
135+
return None
136+
return unicode(value.replace(microsecond=0))
137+
138+
def year_lookup_bounds(self, value):
139+
# Again, no microseconds
140+
first = '%s-01-01 00:00:00'
141+
second = '%s-12-31 23:59:59.99'
142+
return [first % value, second % value]
143+
127144
class DatabaseWrapper(BaseDatabaseWrapper):
128145
features = DatabaseFeatures()
129146
ops = DatabaseOperations()

‎django/db/backends/oracle/base.py‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
"""
66

77
import os
8+
import datetime
9+
import time
810

911
from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util
1012
from django.db.backends.oracle import query
@@ -28,9 +30,7 @@ class DatabaseFeatures(BaseDatabaseFeatures):
2830
supports_tablespaces = True
2931
uses_case_insensitive_names = True
3032
uses_custom_query_class = True
31-
time_field_needs_date = True
3233
interprets_empty_strings_as_nulls = True
33-
date_field_supports_time_value = False
3434

3535
class DatabaseOperations(BaseDatabaseOperations):
3636
def autoinc_sql(self, table, column):
@@ -180,6 +180,21 @@ def start_transaction_sql(self):
180180
def tablespace_sql(self, tablespace, inline=False):
181181
return "%sTABLESPACE %s" % ((inline and "USING INDEX " or ""), self.quote_name(tablespace))
182182

183+
def value_to_db_time(self, value):
184+
if value is None:
185+
return None
186+
if isinstance(value, basestring):
187+
return datetime.datetime(*(time.strptime(value, '%H:%M:%S')[:6]))
188+
return datetime.datetime(1900, 1, 1, value.hour, value.minute,
189+
value.second, value.microsecond)
190+
191+
def year_lookup_bounds_for_date_field(self, value):
192+
first = '%s-01-01'
193+
second = '%s-12-31'
194+
return [first % value, second % value]
195+
196+
197+
183198
class DatabaseWrapper(BaseDatabaseWrapper):
184199
features = DatabaseFeatures()
185200
ops = DatabaseOperations()

‎django/db/backends/sqlite3/base.py‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ def sql_flush(self, style, tables, sequences):
8484
# sql_flush() implementations). Just return SQL at this point
8585
return sql
8686

87+
def year_lookup_bounds(self, value):
88+
first = '%s-01-01'
89+
second = '%s-12-31 23:59:59.999999'
90+
return [first % value, second % value]
91+
92+
8793
class DatabaseWrapper(BaseDatabaseWrapper):
8894
features = DatabaseFeatures()
8995
ops = DatabaseOperations()
@@ -159,7 +165,7 @@ def _sqlite_extract(lookup_type, dt):
159165
dt = util.typecast_timestamp(dt)
160166
except (ValueError, TypeError):
161167
return None
162-
return str(getattr(dt, lookup_type))
168+
return getattr(dt, lookup_type)
163169

164170
def _sqlite_date_trunc(lookup_type, dt):
165171
try:

‎django/db/backends/util.py‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,10 @@ def truncate_name(name, length=None):
117117
hash = md5.md5(name).hexdigest()[:4]
118118

119119
return '%s%s' % (name[:length-4], hash)
120+
121+
def format_number(value, max_digits, decimal_places):
122+
"""
123+
Formats a number into a string with the requisite number of digits and
124+
decimal places.
125+
"""
126+
return u"%.*f" % (decimal_places, value)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /