Changeset 5531 for django/branches/unicode/django/db/models
- Timestamp:
- 06/25/07 07:47:19 (2 years ago)
- Files:
-
- django/branches/unicode (modified) (1 prop)
- django/branches/unicode/django/db/models/base.py (modified) (5 diffs)
- django/branches/unicode/django/db/models/fields/__init__.py (modified) (7 diffs)
- django/branches/unicode/django/db/models/fields/related.py (modified) (2 diffs)
- django/branches/unicode/django/db/models/options.py (modified) (4 diffs)
- django/branches/unicode/django/db/models/query.py (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/unicode
- Property svnmerge-integrated changed from /django/trunk:1-5460 to /django/trunk:1-5530
django/branches/unicode/django/db/models/base.py
r5400 r5531 100 100 def __init__(self, *args, **kwargs): 101 101 dispatcher.send(signal=signals.pre_init, sender=self.__class__, args=args, kwargs=kwargs) 102 102 103 103 # There is a rather weird disparity here; if kwargs, it's set, then args 104 # overrides it. It should be one or the other; don't duplicate the work 104 # overrides it. It should be one or the other; don't duplicate the work 105 105 # The reason for the kwargs check is that standard iterator passes in by 106 106 # args, and nstantiation for iteration is 33% faster. … … 126 126 if isinstance(field.rel, ManyToOneRel): 127 127 kwargs.pop(field.attname, None) 128 128 129 129 # Now we're left with the unprocessed fields that *must* come from 130 130 # keywords, or default. 131 131 132 132 for field in fields_iter: 133 133 if kwargs: … … 151 151 val = getattr(rel_obj, field.rel.get_related_field().attname) 152 152 except AttributeError: 153 raise TypeError("Invalid value: %r should be a %s instance, not a %s" % 153 raise TypeError("Invalid value: %r should be a %s instance, not a %s" % 154 154 (field.name, field.rel.to, type(rel_obj))) 155 155 else: … … 214 214 if pk_set: 215 215 # Determine whether a record with the primary key already exists. 216 cursor.execute("SELECT 1 FROM %s WHERE %s=%%s LIMIT 1" % \ 217 (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)), [pk_val]) 216 cursor.execute("SELECT COUNT(*) FROM %s WHERE %s=%%s" % \ 217 (backend.quote_name(self._meta.db_table), backend.quote_name(self._meta.pk.column)), 218 self._meta.pk.get_db_prep_lookup('exact', pk_val)) 218 219 # If it does already exist, do an UPDATE. 219 if cursor.fetchone() :220 if cursor.fetchone()[0] > 0: 220 221 db_values = [f.get_db_prep_save(f.pre_save(self, False)) for f in non_pks] 221 222 if db_values: … … 224 225 ','.join(['%s=%%s' % backend.quote_name(f.column) for f in non_pks]), 225 226 backend.quote_name(self._meta.pk.column)), 226 db_values + [pk_val])227 db_values + self._meta.pk.get_db_prep_lookup('exact', pk_val)) 227 228 else: 228 229 record_exists = False django/branches/unicode/django/db/models/fields/__init__.py
r5314 r5531 76 76 prepopulate_from=None, unique_for_date=None, unique_for_month=None, 77 77 unique_for_year=None, validator_list=None, choices=None, radio_admin=None, 78 help_text='', db_column=None ):78 help_text='', db_column=None, db_tablespace=None): 79 79 self.name = name 80 80 self.verbose_name = verbose_name … … 82 82 self.maxlength, self.unique = maxlength, unique 83 83 self.blank, self.null = blank, null 84 # Oracle treats the empty string ('') as null, so coerce the null 85 # option whenever '' is a possible value. 86 if self.empty_strings_allowed and settings.DATABASE_ENGINE == 'oracle': 87 self.null = True 84 88 self.core, self.rel, self.default = core, rel, default 85 89 self.editable = editable … … 93 97 self.help_text = help_text 94 98 self.db_column = db_column 99 self.db_tablespace = db_tablespace 95 100 96 101 # Set db_index to True if the field has a relationship and doesn't explicitly set db_index. … … 203 208 return self.default() 204 209 return self.default 205 if not self.empty_strings_allowed or self.null:210 if not self.empty_strings_allowed or (self.null and settings.DATABASE_ENGINE != 'oracle'): 206 211 return None 207 212 return "" … … 808 813 809 814 class NullBooleanField(Field): 815 empty_strings_allowed = False 810 816 def __init__(self, *args, **kwargs): 811 817 kwargs['null'] = True … … 877 883 878 884 def get_db_prep_lookup(self, lookup_type, value): 885 if settings.DATABASE_ENGINE == 'oracle': 886 # Oracle requires a date in order to parse. 887 def prep(value): 888 if isinstance(value, datetime.time): 889 value = datetime.datetime.combine(datetime.date(1900, 1, 1), value) 890 return smart_unicode(value) 891 else: 892 prep = smart_unicode 879 893 if lookup_type == 'range': 880 value = [ smart_unicode(v) for v in value]881 else: 882 value = smart_unicode(value)894 value = [prep(v) for v in value] 895 else: 896 value = prep(value) 883 897 return Field.get_db_prep_lookup(self, lookup_type, value) 884 898 … … 898 912 if settings.DATABASE_ENGINE == 'mysql' and hasattr(value, 'microsecond'): 899 913 value = value.replace(microsecond=0) 900 value = smart_unicode(value) 914 if settings.DATABASE_ENGINE == 'oracle': 915 # cx_Oracle expects a datetime.datetime to persist into TIMESTAMP field. 916 if isinstance(value, datetime.time): 917 value = datetime.datetime(1900, 1, 1, value.hour, value.minute, 918 value.second, value.microsecond) 919 elif isinstance(value, basestring): 920 value = datetime.datetime(*(time.strptime(value, '%H:%M:%S')[:6])) 921 else: 922 value = smart_unicode(value) 901 923 return Field.get_db_prep_save(self, value) 902 924 django/branches/unicode/django/db/models/fields/related.py
r5230 r5531 12 12 from django.dispatch import dispatcher 13 13 14 # For Python 2.3 15 if not hasattr(__builtins__, 'set'): 16 from sets import Set as set 14 try: 15 set 16 except NameError: 17 from sets import Set as set # Python 2.3 fallback 17 18 18 19 # Values for Relation.edit_inline. … … 337 338 target_col_name, ",".join(['%s'] * len(new_ids))), 338 339 [self._pk_val] + list(new_ids)) 339 if cursor.rowcount is not None and cursor.rowcount != 0: 340 existing_ids = set([row[0] for row in cursor.fetchmany(cursor.rowcount)]) 341 else: 342 existing_ids = set() 340 existing_ids = set([row[0] for row in cursor.fetchall()]) 343 341 344 342 # Add the ones that aren't there already django/branches/unicode/django/db/models/options.py
r5372 r5531 16 16 DEFAULT_NAMES = ('verbose_name', 'db_table', 'ordering', 17 17 'unique_together', 'permissions', 'get_latest_by', 18 'order_with_respect_to', 'app_label' )18 'order_with_respect_to', 'app_label', 'db_tablespace') 19 19 20 20 class Options(object): … … 30 30 self.get_latest_by = None 31 31 self.order_with_respect_to = None 32 self.db_tablespace = None 32 33 self.admin = None 33 34 self.meta = meta … … 63 64 64 65 def _prepare(self, model): 66 from django.db import backend 67 from django.db.backends.util import truncate_name 65 68 if self.order_with_respect_to: 66 69 self.order_with_respect_to = self.get_field(self.order_with_respect_to) … … 77 80 if not self.db_table: 78 81 self.db_table = "%s_%s" % (self.app_label, self.module_name) 82 self.db_table = truncate_name(self.db_table, 83 backend.get_max_name_length()) 79 84 80 85 def add_field(self, field): django/branches/unicode/django/db/models/query.py
r5399 r5531 6 6 from django.utils.encoding import smart_unicode 7 7 from django.contrib.contenttypes import generic 8 import datetime 8 9 import operator 9 10 import re 10 11 11 # For Python 2.3 12 if not hasattr(__builtins__, 'set'): 13 from sets import Set as set 12 try: 13 set 14 except NameError: 15 from sets import Set as set # Python 2.3 fallback 14 16 15 17 # The string constant used to separate query parts … … 79 81 return backend.quote_name(word) 80 82 81 class QuerySet(object):83 class _QuerySet(object): 82 84 "Represents a lazy database lookup for a set of objects" 83 85 def __init__(self, model=None): … … 183 185 cursor = connection.cursor() 184 186 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 187 185 188 fill_cache = self._select_related 186 index_end = len(self.model._meta.fields) 189 fields = self.model._meta.fields 190 index_end = len(fields) 191 has_resolve_columns = hasattr(self, 'resolve_columns') 187 192 while 1: 188 193 rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) … … 190 195 raise StopIteration 191 196 for row in rows: 197 if has_resolve_columns: 198 row = self.resolve_columns(row, fields) 192 199 if fill_cache: 193 200 obj, index_end = get_cached_row(klass=self.model, row=row, … … 553 560 return select, " ".join(sql), params 554 561 562 # Use the backend's QuerySet class if it defines one, otherwise use _QuerySet. 563 if hasattr(backend, 'get_query_set_class'): 564 QuerySet = backend.get_query_set_class(_QuerySet) 565 else: 566 QuerySet = _QuerySet 567 555 568 class ValuesQuerySet(QuerySet): 556 569 def __init__(self, *args, **kwargs): … … 567 580 # self._fields is a list of field names to fetch. 568 581 if self._fields: 569 #columns = [self.model._meta.get_field(f, many_to_many=False).column for f in self._fields]570 582 if not self._select: 571 columns = [self.model._meta.get_field(f, many_to_many=False).columnfor f in self._fields]583 fields = [self.model._meta.get_field(f, many_to_many=False) for f in self._fields] 572 584 else: 573 columns = []585 fields = [] 574 586 for f in self._fields: 575 587 if f in [field.name for field in self.model._meta.fields]: 576 columns.append( self.model._meta.get_field(f, many_to_many=False).column)588 fields.append(self.model._meta.get_field(f, many_to_many=False)) 577 589 elif not self._select.has_key( f ): 578 590 raise FieldDoesNotExist, '%s has no field named %r' % ( self.model._meta.object_name, f ) … … 580 592 field_names = self._fields 581 593 else: # Default to all fields. 582 columns = [f.column for f in self.model._meta.fields] 583 field_names = [f.attname for f in self.model._meta.fields] 584 594 fields = self.model._meta.fields 595 field_names = [f.attname for f in fields] 596 597 columns = [f.column for f in fields] 585 598 select = ['%s.%s' % (backend.quote_name(self.model._meta.db_table), backend.quote_name(c)) for c in columns] 586 587 599 # Add any additional SELECTs. 588 600 if self._select: … … 591 603 cursor = connection.cursor() 592 604 cursor.execute("SELECT " + (self._distinct and "DISTINCT " or "") + ",".join(select) + sql, params) 605 606 has_resolve_columns = hasattr(self, 'resolve_columns') 593 607 while 1: 594 608 rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) … … 596 610 raise StopIteration 597 611 for row in rows: 612 if has_resolve_columns: 613 row = self.resolve_columns(row, fields) 598 614 yield dict(zip(field_names, row)) 599 615 … … 606 622 def iterator(self): 607 623 from django.db.backends.util import typecast_timestamp 624 from django.db.models.fields import DateTimeField 608 625 self._order_by = () # Clear this because it'll mess things up otherwise. 609 626 if self._field.null: 610 627 self._where.append('%s.%s IS NOT NULL' % \ 611 628 (backend.quote_name(self.model._meta.db_table), backend.quote_name(self._field.column))) 612 613 629 try: 614 630 select, sql, params = self._get_sql_clause() … … 616 632 raise StopIteration 617 633 618 sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1 %s' % \ 634 table_name = backend.quote_name(self.model._meta.db_table) 635 field_name = backend.quote_name(self._field.column) 636 637 if backend.allows_group_by_ordinal: 638 group_by = '1' 639 else: 640 group_by = backend.get_date_trunc_sql(self._kind, 641 '%s.%s' % (table_name, field_name)) 642 643 sql = 'SELECT %s %s GROUP BY %s ORDER BY 1 %s' % \ 619 644 (backend.get_date_trunc_sql(self._kind, '%s.%s' % (backend.quote_name(self.model._meta.db_table), 620 backend.quote_name(self._field.column))), sql, self._order)645 backend.quote_name(self._field.column))), sql, group_by, self._order) 621 646 cursor = connection.cursor() 622 647 cursor.execute(sql, params) 623 # We have to manually run typecast_timestamp(str()) on the results, because 624 # MySQL doesn't automatically cast the result of date functions as datetime 625 # objects -- MySQL returns the values as strings, instead. 626 return [typecast_timestamp(str(row[0])) for row in cursor.fetchall()] 648 649 has_resolve_columns = hasattr(self, 'resolve_columns') 650 needs_datetime_string_cast = backend.needs_datetime_string_cast 651 dates = [] 652 # It would be better to use self._field here instead of DateTimeField(), 653 # but in Oracle that will result in a list of datetime.date instead of 654 # datetime.datetime. 655 fields = [DateTimeField()] 656 while 1: 657 rows = cursor.fetchmany(GET_ITERATOR_CHUNK_SIZE) 658 if not rows: 659 return dates 660 for row in rows: 661 date = row[0] 662 if has_resolve_columns: 663 date = self.resolve_columns([date], fields)[0] 664 elif needs_datetime_string_cast: 665 date = typecast_timestamp(str(date)) 666 dates.append(date) 627 667 628 668 def _clone(self, klass=None, **kwargs): … … 732 772 table_prefix = backend.quote_name(table_prefix[:-1])+'.' 733 773 field_name = backend.quote_name(field_name) 774 if type(value) == datetime.datetime and backend.get_datetime_cast_sql(): 775 cast_sql = backend.get_datetime_cast_sql() 776 else: 777 cast_sql = '%s' 778 if lookup_type in ('iexact', 'icontains', 'istartswith', 'iendswith') and backend.needs_upper_for_iops: 779 format = 'UPPER(%s%s) %s' 780 else: 781 format = '%s%s %s' 734 782 try: 735 return '%s%s %s' % (table_prefix, field_name, (backend.OPERATOR_MAPPING[lookup_type] % '%s')) 783 return format % (table_prefix, field_name, 784 backend.OPERATOR_MAPPING[lookup_type] % cast_sql) 736 785 except KeyError: 737 786 pass
