Ticket #7560: 7560_get_db_prep_refactor.2.diff
File 7560_get_db_prep_refactor.2.diff, 29.3 KB (added by , 16 years ago) |
---|
-
django/db/backends/__init__.py
diff -r 162b0967db76 django/db/backends/__init__.py
a b 4 4 except ImportError: 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): 9 12 """ … … 36 39 return cursor 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 42 44 class BaseDatabaseFeatures(object): 43 45 allows_group_by_ordinal = True 44 46 inline_fk_references = True 45 needs_datetime_string_cast = True 47 needs_datetime_string_cast = True # uses 48 # django.db.backend.utils.typecast_timetamp 49 # on returned values from dates()? 46 50 supports_constraints = True 47 51 supports_tablespaces = False 48 52 uses_case_insensitive_names = False 49 53 uses_custom_query_class = False 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 58 59 class BaseDatabaseOperations(object): … … 263 264 """Prepares a value for use in a LIKE query.""" 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) # XXX: Why not just str(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) # XXX: Why not just str(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
diff -r 162b0967db76 django/db/backends/mysql/base.py
a b 63 63 inline_fk_references = False 64 64 empty_fetchmany_value = () 65 65 update_can_self_select = False 66 supports_usecs = False67 66 68 67 class DatabaseOperations(BaseDatabaseOperations): 69 68 def date_extract_sql(self, lookup_type, field_name): … … 123 122 return sql 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 # XXX: Why not just str(value)? 131 return unicode(value.replace(microsecond=0)) 132 133 def value_to_db_time(self, value): 134 # MySQL doesn't support microseconds 135 if value is None: 136 return None 137 # XXX: Why not just str(value)? 138 return unicode(value.replace(microsecond=0)) 139 140 def year_lookup_bounds(self, value): 141 # Again, no microseconds 142 first = '%s-01-01 00:00:00' 143 second = '%s-12-31 23:59:59.99' 144 return [first % value, second % value] 126 145 127 146 class DatabaseWrapper(BaseDatabaseWrapper): 128 147 features = DatabaseFeatures() -
django/db/backends/oracle/base.py
diff -r 162b0967db76 django/db/backends/oracle/base.py
a b 5 5 """ 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 10 12 from django.db.backends.oracle import query … … 29 31 supports_tablespaces = True 30 32 uses_case_insensitive_names = True 31 33 uses_custom_query_class = True 32 time_field_needs_date = True33 34 interprets_empty_strings_as_nulls = True 34 date_field_supports_time_value = False35 35 36 36 class DatabaseOperations(BaseDatabaseOperations): 37 37 def autoinc_sql(self, table, column): … … 180 180 181 181 def tablespace_sql(self, tablespace, inline=False): 182 182 return "%sTABLESPACE %s" % ((inline and "USING INDEX " or ""), self.quote_name(tablespace)) 183 184 def value_to_db_time(self, value): 185 if value is None: 186 return None 187 if isinstance(value, basestring): 188 return datetime.datetime(*(time.strptime(value, '%H:%M:%S')[:6])) 189 return datetime.datetime(1900, 1, 1, value.hour, value.minute, 190 value.second, value.microsecond) 191 192 def year_lookup_bounds_for_date_field(self, value): 193 first = '%s-01-01' 194 second = '%s-12-31' 195 return [first % value, second % value] 196 197 183 198 184 199 class DatabaseWrapper(BaseDatabaseWrapper): 185 200 features = DatabaseFeatures() -
django/db/backends/sqlite3/base.py
diff -r 162b0967db76 django/db/backends/sqlite3/base.py
a b 84 84 # sql_flush() implementations). Just return SQL at this point 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() 89 95 ops = DatabaseOperations() … … 159 165 dt = util.typecast_timestamp(dt) 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): 165 171 try: -
django/db/backends/util.py
diff -r 162b0967db76 django/db/backends/util.py
a b 117 117 hash = md5.md5(name).hexdigest()[:4] 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/db/models/fields/__init__.py
diff -r 162b0967db76 django/db/models/fields/__init__.py
a b 217 217 "Returns field's value just before saving." 218 218 return getattr(model_instance, self.attname) 219 219 220 def get_db_prep_value(self, value): 221 """Returns field's value prepared for interacting with the database 222 backend. 223 224 Used by the default implementations of ``get_db_prep_save``and 225 `get_db_prep_lookup``` 226 """ 227 return value 228 220 229 def get_db_prep_save(self, value): 221 230 "Returns field's value prepared for saving into a database." 222 return value231 return self.get_db_prep_value(value) 223 232 224 233 def get_db_prep_lookup(self, lookup_type, value): 225 234 "Returns field's value prepared for database lookup." 226 235 if hasattr(value, 'as_sql'): 227 236 sql, params = value.as_sql() 228 237 return QueryWrapper(('(%s)' % sql), params) 229 if lookup_type in (' exact', 'regex', 'iregex', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search'):238 if lookup_type in ('regex', 'iregex', 'month', 'day', 'search'): 230 239 return [value] 240 elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'): 241 return [self.get_db_prep_value(value)] 231 242 elif lookup_type in ('range', 'in'): 232 return value243 return [self.get_db_prep_value(v) for v in value] 233 244 elif lookup_type in ('contains', 'icontains'): 234 245 return ["%%%s%%" % connection.ops.prep_for_like_query(value)] 235 246 elif lookup_type == 'iexact': … … 245 256 value = int(value) 246 257 except ValueError: 247 258 raise ValueError("The __year lookup type requires an integer argument") 248 if settings.DATABASE_ENGINE == 'sqlite3': 249 first = '%s-01-01' 250 second = '%s-12-31 23:59:59.999999' 251 elif not connection.features.date_field_supports_time_value and self.get_internal_type() == 'DateField': 252 first = '%s-01-01' 253 second = '%s-12-31' 254 elif not connection.features.supports_usecs: 255 first = '%s-01-01 00:00:00' 256 second = '%s-12-31 23:59:59.99' 259 260 if self.get_internal_type() == 'DateField': 261 return connection.ops.year_lookup_bounds_for_date_field(value) 257 262 else: 258 first = '%s-01-01 00:00:00' 259 second = '%s-12-31 23:59:59.999999' 260 return [first % value, second % value] 263 return connection.ops.year_lookup_bounds(value) 264 261 265 raise TypeError("Field has invalid lookup: %s" % lookup_type) 262 266 263 267 def has_default(self): … … 449 453 except (TypeError, ValueError): 450 454 raise validators.ValidationError, _("This value must be an integer.") 451 455 456 def get_db_prep_value(self, value): 457 if value is None: 458 return None 459 return int(value) 460 452 461 def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True): 453 462 if not rel: 454 463 return [] # Don't add a FormField unless it's in a related context. … … 487 496 if value in ('t', 'True', '1'): return True 488 497 if value in ('f', 'False', '0'): return False 489 498 raise validators.ValidationError, _("This value must be either True or False.") 499 500 def get_db_prep_value(self, value): 501 if value is None: 502 return None 503 return bool(value) 490 504 491 505 def get_manipulator_field_objs(self): 492 506 return [oldforms.CheckboxField] … … 549 563 except ValueError: 550 564 raise validators.ValidationError, _('Enter a valid date in YYYY-MM-DD format.') 551 565 552 def get_db_prep_lookup(self, lookup_type, value):553 if lookup_type in ('range', 'in'):554 value = [smart_unicode(v) for v in value]555 elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte') and hasattr(value, 'strftime'):556 value = datetime_safe.new_date(value).strftime('%Y-%m-%d')557 else:558 value = smart_unicode(value)559 return Field.get_db_prep_lookup(self, lookup_type, value)560 561 566 def pre_save(self, model_instance, add): 562 567 if self.auto_now or (self.auto_now_add and add): 563 568 value = datetime.datetime.now() … … 581 586 else: 582 587 return self.editable or self.auto_now or self.auto_now_add 583 588 584 def get_db_prep_save(self, value): 585 # Casts dates into string format for entry into database. 586 if value is not None: 587 try: 588 value = datetime_safe.new_date(value).strftime('%Y-%m-%d') 589 except AttributeError: 590 # If value is already a string it won't have a strftime method, 591 # so we'll just let it pass through. 592 pass 593 return Field.get_db_prep_save(self, value) 589 def get_db_prep_value(self, value): 590 # Casts dates into the format expected by the backend 591 return connection.ops.value_to_db_date(self.to_python(value)) 594 592 595 593 def get_manipulator_field_objs(self): 596 594 return [oldforms.DateField] … … 619 617 return value 620 618 if isinstance(value, datetime.date): 621 619 return datetime.datetime(value.year, value.month, value.day) 620 621 # Attempt to parse a datetime: 622 value = smart_str(value) 623 # split usecs, because they are not recognized by strptime. 624 if '.' in value: 625 try: 626 value, usecs = value.split('.') 627 usecs = int(usecs) 628 except ValueError: 629 raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM[ss[.uuuuuu]] format.') 630 else: 631 usecs = 0 632 kwargs = {'microsecond': usecs} 622 633 try: # Seconds are optional, so try converting seconds first. 623 return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6]) 634 return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6], 635 **kwargs) 636 624 637 except ValueError: 625 638 try: # Try without seconds. 626 return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5]) 639 return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5], 640 **kwargs) 627 641 except ValueError: # Try without hour/minutes/seconds. 628 642 try: 629 return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3]) 643 return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3], 644 **kwargs) 630 645 except ValueError: 631 raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM format.')646 raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM[ss[.uuuuuu]] format.') 632 647 633 def get_db_prep_save(self, value): 634 # Casts dates into string format for entry into database. 635 if value is not None: 636 # MySQL will throw a warning if microseconds are given, because it 637 # doesn't support microseconds. 638 if not connection.features.supports_usecs and hasattr(value, 'microsecond'): 639 value = value.replace(microsecond=0) 640 value = smart_unicode(value) 641 return Field.get_db_prep_save(self, value) 642 643 def get_db_prep_lookup(self, lookup_type, value): 644 if lookup_type in ('range', 'in'): 645 value = [smart_unicode(v) for v in value] 646 else: 647 value = smart_unicode(value) 648 return Field.get_db_prep_lookup(self, lookup_type, value) 648 def get_db_prep_value(self, value): 649 # Casts dates into the format expected by the backend 650 return connection.ops.value_to_db_datetime(self.to_python(value)) 649 651 650 652 def get_manipulator_field_objs(self): 651 653 return [oldforms.DateField, oldforms.TimeField] … … 710 712 Formats a number into a string with the requisite number of digits and 711 713 decimal places. 712 714 """ 713 num_chars = self.max_digits 714 # Allow for a decimal point 715 if self.decimal_places > 0: 716 num_chars += 1 717 # Allow for a minus sign 718 if value < 0: 719 num_chars += 1 715 # Method moved to django.db.backends.util. 716 # 717 # It is preserved because it is used by the oracle backend 718 # (django.db.backends.oracle.query), and also for 719 # backwards-compatibility with any external code which may have used 720 # this method. 721 from django.db.backends import util 722 return util.format_number(value, self.max_digits, self.decimal_places) 720 723 721 return u"%.*f" % (self.decimal_places, value) 722 723 def get_db_prep_save(self, value): 724 value = self._format(value) 725 return super(DecimalField, self).get_db_prep_save(value) 726 727 def get_db_prep_lookup(self, lookup_type, value): 728 if lookup_type in ('range', 'in'): 729 value = [self._format(v) for v in value] 730 else: 731 value = self._format(value) 732 return super(DecimalField, self).get_db_prep_lookup(lookup_type, value) 724 def get_db_prep_value(self, value): 725 return connection.ops.value_to_db_decimal(value, self.max_digits, 726 self.decimal_places) 733 727 734 728 def get_manipulator_field_objs(self): 735 729 return [curry(oldforms.DecimalField, max_digits=self.max_digits, decimal_places=self.decimal_places)] … … 768 762 def get_internal_type(self): 769 763 return "FileField" 770 764 771 def get_db_prep_ save(self, value):765 def get_db_prep_value(self, value): 772 766 "Returns field's value prepared for saving into a database." 773 767 # Need to convert UploadedFile objects provided via a form to unicode for database insertion 774 768 if hasattr(value, 'name'): … … 909 903 class FloatField(Field): 910 904 empty_strings_allowed = False 911 905 906 def get_db_prep_value(self, value): 907 if value is None: 908 return None 909 return float(value) 910 912 911 def get_manipulator_field_objs(self): 913 912 return [oldforms.FloatField] 914 913 … … 956 955 957 956 class IntegerField(Field): 958 957 empty_strings_allowed = False 958 def get_db_prep_value(self, value): 959 if value is None: 960 return None 961 return int(value) 962 959 963 def get_manipulator_field_objs(self): 960 964 return [oldforms.IntegerField] 961 965 … … 1003 1007 if value in ('f', 'False', '0'): return False 1004 1008 raise validators.ValidationError, _("This value must be either None, True or False.") 1005 1009 1010 def get_db_prep_value(self, value): 1011 if value is None: 1012 return None 1013 return bool(value) 1014 1006 1015 def get_manipulator_field_objs(self): 1007 1016 return [oldforms.NullBooleanField] 1008 1017 … … 1015 1024 defaults.update(kwargs) 1016 1025 return super(NullBooleanField, self).formfield(**defaults) 1017 1026 1018 class PhoneNumberField( IntegerField):1027 class PhoneNumberField(Field): 1019 1028 def get_manipulator_field_objs(self): 1020 1029 return [oldforms.PhoneNumberField] 1021 1030 … … 1097 1106 def get_internal_type(self): 1098 1107 return "TimeField" 1099 1108 1100 def get_db_prep_lookup(self, lookup_type, value): 1101 if connection.features.time_field_needs_date: 1102 # Oracle requires a date in order to parse. 1103 def prep(value): 1104 if isinstance(value, datetime.time): 1105 value = datetime.datetime.combine(datetime.date(1900, 1, 1), value) 1106 return smart_unicode(value) 1109 def to_python(self, value): 1110 if value is None: 1111 return None 1112 if isinstance(value, datetime.time): 1113 return value 1114 1115 # Attempt to parse a datetime: 1116 value = smart_str(value) 1117 # split usecs, because they are not recognized by strptime. 1118 if '.' in value: 1119 try: 1120 value, usecs = value.split('.') 1121 usecs = int(usecs) 1122 except ValueError: 1123 raise validators.ValidationError, _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.') 1107 1124 else: 1108 prep = smart_unicode 1109 if lookup_type in ('range', 'in'): 1110 value = [prep(v) for v in value] 1111 else: 1112 value = prep(value) 1113 return Field.get_db_prep_lookup(self, lookup_type, value) 1125 usecs = 0 1126 kwargs = {'microsecond': usecs} 1127 1128 try: # Seconds are optional, so try converting seconds first. 1129 return datetime.time(*time.strptime(value, '%H:%M:%S')[3:6], 1130 **kwargs) 1131 except ValueError: 1132 try: # Try without seconds. 1133 return datetime.datetime(*time.strptime(value, '%H:%M')[:5], 1134 **kwargs) 1135 except ValueError: 1136 raise validators.ValidationError, _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.') 1114 1137 1115 1138 def pre_save(self, model_instance, add): 1116 1139 if self.auto_now or (self.auto_now_add and add): … … 1120 1143 else: 1121 1144 return super(TimeField, self).pre_save(model_instance, add) 1122 1145 1123 def get_db_prep_save(self, value): 1124 # Casts dates into string format for entry into database. 1125 if value is not None: 1126 # MySQL will throw a warning if microseconds are given, because it 1127 # doesn't support microseconds. 1128 if not connection.features.supports_usecs and hasattr(value, 'microsecond'): 1129 value = value.replace(microsecond=0) 1130 if connection.features.time_field_needs_date: 1131 # cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field. 1132 if isinstance(value, datetime.time): 1133 value = datetime.datetime(1900, 1, 1, value.hour, value.minute, 1134 value.second, value.microsecond) 1135 elif isinstance(value, basestring): 1136 value = datetime.datetime(*(time.strptime(value, '%H:%M:%S')[:6])) 1137 else: 1138 value = smart_unicode(value) 1139 return Field.get_db_prep_save(self, value) 1146 def get_db_prep_value(self, value): 1147 # Casts times into the format expected by the backend 1148 return connection.ops.value_to_db_time(self.to_python(value)) 1140 1149 1141 1150 def get_manipulator_field_objs(self): 1142 1151 return [oldforms.TimeField] -
docs/custom_model_fields.txt
diff -r 162b0967db76 docs/custom_model_fields.txt
a b 385 385 called when it is created, you should be using `The SubfieldBase metaclass`_ 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 392 392 (as opposed to serialization). The ``value`` parameter is the current value of … … 399 399 class HandField(models.Field): 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)`` 407 417 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ … … 440 450 and pass the rest of the ``get_db_prep_lookup()`` method of the parent class. 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. 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. 449 456 450 For example:: 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): 453 470 # ... … … 455 472 def get_db_prep_lookup(self, lookup_type, value): 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) 463 480 … … 557 574 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 563 580 -------------------- -
tests/modeltests/custom_methods/models.py
diff -r 162b0967db76 tests/modeltests/custom_methods/models.py
a b 31 31 SELECT id, headline, pub_date 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(). 37 38 return [self.__class__(*row) for row in cursor.fetchall()] -
tests/regressiontests/model_fields/tests.py
diff -r 162b0967db76 tests/regressiontests/model_fields/tests.py
a b 20 20 >>> x = f.to_python(2) 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 """ -
tests/regressiontests/model_regress/models.py
diff -r 162b0967db76 tests/regressiontests/model_regress/models.py
a b 28 28 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': """ 33 36 (NOTE: Part of the regression test here is merely parsing the model … … 68 71 >>> [p.when for p in Party.objects.filter(when__year = 1998)] 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 }