Changeset 8131
- Timestamp:
- 07/29/08 00:09:29 (4 months ago)
- Files:
-
- django/trunk/django/db/backends/__init__.py (modified) (5 diffs)
- django/trunk/django/db/backends/mysql/base.py (modified) (2 diffs)
- django/trunk/django/db/backends/oracle/base.py (modified) (3 diffs)
- django/trunk/django/db/backends/sqlite3/base.py (modified) (2 diffs)
- django/trunk/django/db/backends/util.py (modified) (1 diff)
- django/trunk/django/db/models/fields/__init__.py (modified) (16 diffs)
- django/trunk/docs/custom_model_fields.txt (modified) (5 diffs)
- django/trunk/tests/modeltests/custom_methods/models.py (modified) (1 diff)
- django/trunk/tests/modeltests/validation/models.py (modified) (4 diffs)
- django/trunk/tests/regressiontests/model_fields/tests.py (modified) (1 diff)
- django/trunk/tests/regressiontests/model_regress/models.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/db/backends/__init__.py
r7926 r8131 5 5 # Import copy of _thread_local.py from Python 2.4 6 6 from django.utils._threading_local import local 7 8 from django.db.backends import util 9 from django.utils import datetime_safe 7 10 8 11 class BaseDatabaseWrapper(local): … … 37 40 38 41 def make_debug_cursor(self, cursor): 39 from django.db.backends import util40 42 return util.CursorDebugWrapper(cursor, self) 41 43 … … 43 45 allows_group_by_ordinal = True 44 46 inline_fk_references = True 47 # True if django.db.backend.utils.typecast_timestamp is used on values 48 # returned from dates() calls. 45 49 needs_datetime_string_cast = True 46 50 supports_constraints = True … … 50 54 empty_fetchmany_value = [] 51 55 update_can_self_select = True 52 supports_usecs = True53 time_field_needs_date = False54 56 interprets_empty_strings_as_nulls = False 55 date_field_supports_time_value = True56 57 can_use_chunked_reads = True 57 58 … … 264 265 from django.utils.encoding import smart_unicode 265 266 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/trunk/django/db/backends/mysql/base.py
r7852 r8131 64 64 empty_fetchmany_value = () 65 65 update_can_self_select = False 66 supports_usecs = False67 66 68 67 class DatabaseOperations(BaseDatabaseOperations): … … 124 123 else: 125 124 return [] 125 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] 126 143 127 144 class DatabaseWrapper(BaseDatabaseWrapper): django/trunk/django/db/backends/oracle/base.py
r8046 r8131 6 6 7 7 import os 8 import datetime 9 import time 8 10 9 11 from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util … … 29 31 uses_case_insensitive_names = True 30 32 uses_custom_query_class = True 31 time_field_needs_date = True32 33 interprets_empty_strings_as_nulls = True 33 date_field_supports_time_value = False34 34 35 35 class DatabaseOperations(BaseDatabaseOperations): … … 180 180 def tablespace_sql(self, tablespace, inline=False): 181 181 return "%sTABLESPACE %s" % ((inline and "USING INDEX " or ""), self.quote_name(tablespace)) 182 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 182 197 183 198 class DatabaseWrapper(BaseDatabaseWrapper): django/trunk/django/db/backends/sqlite3/base.py
r7956 r8131 85 85 return sql 86 86 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 87 93 class DatabaseWrapper(BaseDatabaseWrapper): 88 94 features = DatabaseFeatures() … … 160 166 except (ValueError, TypeError): 161 167 return None 162 return str(getattr(dt, lookup_type))168 return getattr(dt, lookup_type) 163 169 164 170 def _sqlite_date_trunc(lookup_type, dt): django/trunk/django/db/backends/util.py
r7259 r8131 118 118 119 119 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) django/trunk/django/db/models/fields/__init__.py
r8127 r8131 219 219 return getattr(model_instance, self.attname) 220 220 221 def get_db_prep_value(self, value): 222 """Returns field's value prepared for interacting with the database 223 backend. 224 225 Used by the default implementations of ``get_db_prep_save``and 226 `get_db_prep_lookup``` 227 """ 228 return value 229 221 230 def get_db_prep_save(self, value): 222 231 "Returns field's value prepared for saving into a database." 223 return value232 return self.get_db_prep_value(value) 224 233 225 234 def get_db_prep_lookup(self, lookup_type, value): … … 228 237 sql, params = value.as_sql() 229 238 return QueryWrapper(('(%s)' % sql), params) 230 if lookup_type in (' exact', 'regex', 'iregex', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search'):239 if lookup_type in ('regex', 'iregex', 'month', 'day', 'search'): 231 240 return [value] 241 elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'): 242 return [self.get_db_prep_value(value)] 232 243 elif lookup_type in ('range', 'in'): 233 return value244 return [self.get_db_prep_value(v) for v in value] 234 245 elif lookup_type in ('contains', 'icontains'): 235 246 return ["%%%s%%" % connection.ops.prep_for_like_query(value)] … … 247 258 except ValueError: 248 259 raise ValueError("The __year lookup type requires an integer argument") 249 if settings.DATABASE_ENGINE == 'sqlite3': 250 first = '%s-01-01' 251 second = '%s-12-31 23:59:59.999999' 252 elif not connection.features.date_field_supports_time_value and self.get_internal_type() == 'DateField': 253 first = '%s-01-01' 254 second = '%s-12-31' 255 elif not connection.features.supports_usecs: 256 first = '%s-01-01 00:00:00' 257 second = '%s-12-31 23:59:59.99' 260 261 if self.get_internal_type() == 'DateField': 262 return connection.ops.year_lookup_bounds_for_date_field(value) 258 263 else: 259 first = '%s-01-01 00:00:00' 260 second = '%s-12-31 23:59:59.999999' 261 return [first % value, second % value] 264 return connection.ops.year_lookup_bounds(value) 265 262 266 raise TypeError("Field has invalid lookup: %s" % lookup_type) 263 267 … … 458 462 raise validators.ValidationError, _("This value must be an integer.") 459 463 464 def get_db_prep_value(self, value): 465 if value is None: 466 return None 467 return int(value) 468 460 469 def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True): 461 470 if not rel: … … 498 507 if value in ('f', 'False', '0'): return False 499 508 raise validators.ValidationError, _("This value must be either True or False.") 509 510 def get_db_prep_value(self, value): 511 if value is None: 512 return None 513 return bool(value) 500 514 501 515 def get_manipulator_field_objs(self): … … 560 574 raise validators.ValidationError, _('Enter a valid date in YYYY-MM-DD format.') 561 575 562 def get_db_prep_lookup(self, lookup_type, value):563 if lookup_type in ('range', 'in'):564 value = [smart_unicode(v) for v in value]565 elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte') and hasattr(value, 'strftime'):566 value = datetime_safe.new_date(value).strftime('%Y-%m-%d')567 else:568 value = smart_unicode(value)569 return Field.get_db_prep_lookup(self, lookup_type, value)570 571 576 def pre_save(self, model_instance, add): 572 577 if self.auto_now or (self.auto_now_add and add): … … 592 597 return self.editable or self.auto_now or self.auto_now_add 593 598 594 def get_db_prep_save(self, value): 595 # Casts dates into string format for entry into database. 596 if value is not None: 597 try: 598 value = datetime_safe.new_date(value).strftime('%Y-%m-%d') 599 except AttributeError: 600 # If value is already a string it won't have a strftime method, 601 # so we'll just let it pass through. 602 pass 603 return Field.get_db_prep_save(self, value) 599 def get_db_prep_value(self, value): 600 # Casts dates into the format expected by the backend 601 return connection.ops.value_to_db_date(self.to_python(value)) 604 602 605 603 def get_manipulator_field_objs(self): … … 630 628 if isinstance(value, datetime.date): 631 629 return datetime.datetime(value.year, value.month, value.day) 630 631 # Attempt to parse a datetime: 632 value = smart_str(value) 633 # split usecs, because they are not recognized by strptime. 634 if '.' in value: 635 try: 636 value, usecs = value.split('.') 637 usecs = int(usecs) 638 except ValueError: 639 raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM[ss[.uuuuuu]] format.') 640 else: 641 usecs = 0 642 kwargs = {'microsecond': usecs} 632 643 try: # Seconds are optional, so try converting seconds first. 633 return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6]) 644 return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6], 645 **kwargs) 646 634 647 except ValueError: 635 648 try: # Try without seconds. 636 return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5]) 649 return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5], 650 **kwargs) 637 651 except ValueError: # Try without hour/minutes/seconds. 638 652 try: 639 return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3]) 653 return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3], 654 **kwargs) 640 655 except ValueError: 641 raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM format.') 642 643 def get_db_prep_save(self, value): 644 # Casts dates into string format for entry into database. 645 if value is not None: 646 # MySQL will throw a warning if microseconds are given, because it 647 # doesn't support microseconds. 648 if not connection.features.supports_usecs and hasattr(value, 'microsecond'): 649 value = value.replace(microsecond=0) 650 value = smart_unicode(value) 651 return Field.get_db_prep_save(self, value) 652 653 def get_db_prep_lookup(self, lookup_type, value): 654 if lookup_type in ('range', 'in'): 655 value = [smart_unicode(v) for v in value] 656 else: 657 value = smart_unicode(value) 658 return Field.get_db_prep_lookup(self, lookup_type, value) 656 raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM[ss[.uuuuuu]] format.') 657 658 def get_db_prep_value(self, value): 659 # Casts dates into the format expected by the backend 660 return connection.ops.value_to_db_datetime(self.to_python(value)) 659 661 660 662 def get_manipulator_field_objs(self): … … 721 723 decimal places. 722 724 """ 723 num_chars = self.max_digits 724 # Allow for a decimal point 725 if self.decimal_places > 0: 726 num_chars += 1 727 # Allow for a minus sign 728 if value < 0: 729 num_chars += 1 730 731 return u"%.*f" % (self.decimal_places, value) 732 733 def get_db_prep_save(self, value): 734 value = self._format(value) 735 return super(DecimalField, self).get_db_prep_save(value) 736 737 def get_db_prep_lookup(self, lookup_type, value): 738 if lookup_type in ('range', 'in'): 739 value = [self._format(v) for v in value] 740 else: 741 value = self._format(value) 742 return super(DecimalField, self).get_db_prep_lookup(lookup_type, value) 725 # Method moved to django.db.backends.util. 726 # 727 # It is preserved because it is used by the oracle backend 728 # (django.db.backends.oracle.query), and also for 729 # backwards-compatibility with any external code which may have used 730 # this method. 731 from django.db.backends import util 732 return util.format_number(value, self.max_digits, self.decimal_places) 733 734 def get_db_prep_value(self, value): 735 return connection.ops.value_to_db_decimal(value, self.max_digits, 736 self.decimal_places) 743 737 744 738 def get_manipulator_field_objs(self): … … 779 773 return "FileField" 780 774 781 def get_db_prep_ save(self, value):775 def get_db_prep_value(self, value): 782 776 "Returns field's value prepared for saving into a database." 783 777 # Need to convert UploadedFile objects provided via a form to unicode for database insertion … … 920 914 empty_strings_allowed = False 921 915 916 def get_db_prep_value(self, value): 917 if value is None: 918 return None 919 return float(value) 920 922 921 def get_manipulator_field_objs(self): 923 922 return [oldforms.FloatField] … … 967 966 class IntegerField(Field): 968 967 empty_strings_allowed = False 968 def get_db_prep_value(self, value): 969 if value is None: 970 return None 971 return int(value) 972 969 973 def get_manipulator_field_objs(self): 970 974 return [oldforms.IntegerField] … … 1014 1018 raise validators.ValidationError, _("This value must be either None, True or False.") 1015 1019 1020 def get_db_prep_value(self, value): 1021 if value is None: 1022 return None 1023 return bool(value) 1024 1016 1025 def get_manipulator_field_objs(self): 1017 1026 return [oldforms.NullBooleanField] … … 1026 1035 return super(NullBooleanField, self).formfield(**defaults) 1027 1036 1028 class PhoneNumberField( IntegerField):1037 class PhoneNumberField(Field): 1029 1038 def get_manipulator_field_objs(self): 1030 1039 return [oldforms.PhoneNumberField] … … 1108 1117 return "TimeField" 1109 1118 1110 def get_db_prep_lookup(self, lookup_type, value): 1111 if connection.features.time_field_needs_date: 1112 # Oracle requires a date in order to parse. 1113 def prep(value): 1114 if isinstance(value, datetime.time): 1115 value = datetime.datetime.combine(datetime.date(1900, 1, 1), value) 1116 return smart_unicode(value) 1117 else: 1118 prep = smart_unicode 1119 if lookup_type in ('range', 'in'): 1120 value = [prep(v) for v in value] 1121 else: 1122 value = prep(value) 1123 return Field.get_db_prep_lookup(self, lookup_type, value) 1119 def to_python(self, value): 1120 if value is None: 1121 return None 1122 if isinstance(value, datetime.time): 1123 return value 1124 1125 # Attempt to parse a datetime: 1126 value = smart_str(value) 1127 # split usecs, because they are not recognized by strptime. 1128 if '.' in value: 1129 try: 1130 value, usecs = value.split('.') 1131 usecs = int(usecs) 1132 except ValueError: 1133 raise validators.ValidationError, _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.') 1134 else: 1135 usecs = 0 1136 kwargs = {'microsecond': usecs} 1137 1138 try: # Seconds are optional, so try converting seconds first. 1139 return datetime.time(*time.strptime(value, '%H:%M:%S')[3:6], 1140 **kwargs) 1141 except ValueError: 1142 try: # Try without seconds. 1143 return datetime.time(*time.strptime(value, '%H:%M')[3:5], 1144 **kwargs) 1145 except ValueError: 1146 raise validators.ValidationError, _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.') 1124 1147 1125 1148 def pre_save(self, model_instance, add): … … 1131 1154 return super(TimeField, self).pre_save(model_instance, add) 1132 1155 1133 def get_db_prep_save(self, value): 1134 # Casts dates into string format for entry into database. 1135 if value is not None: 1136 # MySQL will throw a warning if microseconds are given, because it 1137 # doesn't support microseconds. 1138 if not connection.features.supports_usecs and hasattr(value, 'microsecond'): 1139 value = value.replace(microsecond=0) 1140 if connection.features.time_field_needs_date: 1141 # cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field. 1142 if isinstance(value, datetime.time): 1143 value = datetime.datetime(1900, 1, 1, value.hour, value.minute, 1144 value.second, value.microsecond) 1145 elif isinstance(value, basestring): 1146 value = datetime.datetime(*(time.strptime(value, '%H:%M:%S')[:6])) 1147 else: 1148 value = smart_unicode(value) 1149 return Field.get_db_prep_save(self, value) 1156 def get_db_prep_value(self, value): 1157 # Casts times into the format expected by the backend 1158 return connection.ops.value_to_db_time(self.to_python(value)) 1150 1159 1151 1160 def get_manipulator_field_objs(self): django/trunk/docs/custom_model_fields.txt
r8125 r8131 386 386 mentioned earlier. Otherwise ``to_python()`` won't be called automatically. 387 387 388 ``get_db_prep_ save(self, value)``389 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 388 ``get_db_prep_value(self, value)`` 389 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 390 390 391 391 This is the reverse of ``to_python()`` when working with the database backends … … 400 400 # ... 401 401 402 def get_db_prep_ save(self, value):402 def get_db_prep_value(self, value): 403 403 return ''.join([''.join(l) for l in (value.north, 404 404 value.east, value.south, value.west)]) 405 406 ``get_db_prep_save(self, value)`` 407 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 408 409 Same as the above, but called when the Field value must be *saved* to the 410 database. As the default implementation just calls ``get_db_prep_value``, you 411 shouldn't need to implement this method unless your custom field need a special 412 conversion when being saved that is not the same as the used for normal query 413 parameters (which is implemented by ``get_db_prep_value``). 414 405 415 406 416 ``pre_save(self, model_instance, add)`` … … 441 451 442 452 If you needed to implement ``get_db_prep_save()``, you will usually need to 443 implement ``get_db_prep_lookup()``. The usual reason is because of the 444 ``range`` and ``in`` lookups. In these case, you will passed a list of 445 objects (presumably of the right type) and will need to convert them to a list 446 of things of the right type for passing to the database. Sometimes you can 447 reuse ``get_db_prep_save()``, or at least factor out some common pieces from 448 both methods into a help function. 449 450 For example:: 453 implement ``get_db_prep_lookup()``. If you don't, ``get_db_prep_value`` will be 454 called by the default implementation, to manage ``exact``, ``gt``, ``gte``, 455 ``lt``, ``lte``, ``in`` and ``range`` lookups. 456 457 You may also want to implement this method to limit the lookup types that could 458 be used with your custom field type. 459 460 Note that, for ``range`` and ``in`` lookups, ``get_db_prep_lookup`` will receive 461 a list of objects (presumably of the right type) and will need to convert them 462 to a list of things of the right type for passing to the database. Most of the 463 time, you can reuse ``get_db_prep_value()``, or at least factor out some common 464 pieces. 465 466 For example, the following code implements ``get_db_prep_lookup`` to limit the 467 accepted lookup types to ``exact`` and ``in``:: 451 468 452 469 class HandField(models.Field): … … 456 473 # We only handle 'exact' and 'in'. All others are errors. 457 474 if lookup_type == 'exact': 458 return self.get_db_prep_ save(value)475 return self.get_db_prep_value(value) 459 476 elif lookup_type == 'in': 460 return [self.get_db_prep_ save(v) for v in value]477 return [self.get_db_prep_value(v) for v in value] 461 478 else: 462 479 raise TypeError('Lookup type %r not supported.' % lookup_type) … … 558 575 def flatten_data(self, follow, obj=None): 559 576 value = self._get_val_from_obj(obj) 560 return {self.attname: self.get_db_prep_ save(value)}577 return {self.attname: self.get_db_prep_value(value)} 561 578 562 579 Some general advice django/trunk/tests/modeltests/custom_methods/models.py
r5876 r8131 32 32 FROM custom_methods_article 33 33 WHERE pub_date = %s 34 AND id != %s""", [str(self.pub_date), self.id]) 34 AND id != %s""", [connection.ops.value_to_db_date(self.pub_date), 35 self.id]) 35 36 # The asterisk in "(*row)" tells Python to expand the list into 36 37 # positional arguments to Article(). django/trunk/tests/modeltests/validation/models.py
r7322 r8131 17 17 favorite_moment = models.DateTimeField() 18 18 email = models.EmailField() 19 best_time = models.TimeField() 19 20 20 21 def __unicode__(self): … … 29 30 ... 'birthdate': datetime.date(2000, 5, 3), 30 31 ... 'favorite_moment': datetime.datetime(2002, 4, 3, 13, 23), 31 ... 'email': 'john@example.com' 32 ... 'email': 'john@example.com', 33 ... 'best_time': datetime.time(16, 20), 32 34 ... } 33 35 >>> p = Person(**valid_params) … … 131 133 datetime.datetime(2002, 4, 3, 0, 0) 132 134 135 >>> p = Person(**dict(valid_params, best_time='16:20:00')) 136 >>> p.validate() 137 {} 138 >>> p.best_time 139 datetime.time(16, 20) 140 141 >>> p = Person(**dict(valid_params, best_time='16:20')) 142 >>> p.validate() 143 {} 144 >>> p.best_time 145 datetime.time(16, 20) 146 147 >>> p = Person(**dict(valid_params, best_time='bar')) 148 >>> p.validate()['best_time'] 149 [u'Enter a valid time in HH:MM[:ss[.uuuuuu]] format.'] 150 133 151 >>> p = Person(**dict(valid_params, email='john@example.com')) 134 152 >>> p.validate() … … 154 172 >>> errors['birthdate'] 155 173 [u'This field is required.'] 174 >>> errors['best_time'] 175 [u'This field is required.'] 156 176 157 177 """} django/trunk/tests/regressiontests/model_fields/tests.py
r7797 r8131 21 21 >>> y = f.to_python('2.6') 22 22 23 >>> f. get_db_prep_save(x)23 >>> f._format(x) 24 24 u'2.0' 25 >>> f. get_db_prep_save(y)25 >>> f._format(y) 26 26 u'2.6' 27 >>> f.get_db_prep_save(None) 28 >>> f.get_db_prep_lookup('exact', x) 29 [u'2.0'] 30 >>> f.get_db_prep_lookup('exact', y) 31 [u'2.6'] 27 >>> f._format(None) 32 28 >>> f.get_db_prep_lookup('exact', None) 33 29 [None] 34 30 31 # DateTimeField and TimeField to_python should support usecs: 32 >>> f = DateTimeField() 33 >>> f.to_python('2001-01-02 03:04:05.000006') 34 datetime.datetime(2001, 1, 2, 3, 4, 5, 6) 35 >>> f.to_python('2001-01-02 03:04:05.999999') 36 datetime.datetime(2001, 1, 2, 3, 4, 5, 999999) 37 38 >>> f = TimeField() 39 >>> f.to_python('01:02:03.000004') 40 datetime.time(1, 2, 3, 4) 41 >>> f.to_python('01:02:03.999999') 42 datetime.time(1, 2, 3, 999999) 43 44 35 45 """ django/trunk/tests/regressiontests/model_regress/models.py
r7359 r8131 29 29 class Party(models.Model): 30 30 when = models.DateField() 31 32 class Event(models.Model): 33 when = models.DateTimeField() 31 34 32 35 __test__ = {'API_TESTS': """ … … 69 72 [datetime.date(1998, 12, 31)] 70 73 74 # Check that get_next_by_FIELD and get_previous_by_FIELD don't crash when we 75 # have usecs values stored on the database 76 # 77 # [It crashed after the Field.get_db_prep_* refactor, because on most backends 78 # DateTimeFields supports usecs, but DateTimeField.to_python didn't recognize 79 # them. (Note that Model._get_next_or_previous_by_FIELD coerces values to 80 # strings)] 81 # 82 >>> e = Event.objects.create(when = datetime.datetime(2000, 1, 1, 16, 0, 0)) 83 >>> e = Event.objects.create(when = datetime.datetime(2000, 1, 1, 6, 1, 1)) 84 >>> e = Event.objects.create(when = datetime.datetime(2000, 1, 1, 13, 1, 1)) 85 >>> e = Event.objects.create(when = datetime.datetime(2000, 1, 1, 12, 0, 20, 24)) 86 >>> e.get_next_by_when().when 87 datetime.datetime(2000, 1, 1, 13, 1, 1) 88 >>> e.get_previous_by_when().when 89 datetime.datetime(2000, 1, 1, 6, 1, 1) 71 90 """ 72 91 }
