Django

Code

Show
Ignore:
Timestamp:
08/05/08 12:15:33 (4 months ago)
Author:
jbronn
Message:

gis: Merged revisions 7981-8001,8003-8011,8013-8033,8035-8036,8038-8039,8041-8063,8065-8076,8078-8139,8141-8154,8156-8214 via svnmerge from trunk.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis

    • Property svnmerge-integrated changed from /django/trunk:1-7978 to /django/trunk:1-8214
  • django/branches/gis/django/db/backends/__init__.py

    r7979 r8215  
    55    # Import copy of _thread_local.py from Python 2.4 
    66    from django.utils._threading_local import local 
     7 
     8from django.db.backends import util 
     9from django.utils import datetime_safe 
    710 
    811class BaseDatabaseWrapper(local): 
     
    3740 
    3841    def make_debug_cursor(self, cursor): 
    39         from django.db.backends import util 
    4042        return util.CursorDebugWrapper(cursor, self) 
    4143 
     
    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 
     
    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 
     
    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 datetime 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 time 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/branches/gis/django/db/backends/mysql/base.py

    r7918 r8215  
    6464    empty_fetchmany_value = () 
    6565    update_can_self_select = False 
    66     supports_usecs = False 
    6766 
    6867class DatabaseOperations(BaseDatabaseOperations): 
     
    124123        else: 
    125124            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] 
    126143 
    127144class DatabaseWrapper(BaseDatabaseWrapper): 
  • django/branches/gis/django/db/backends/oracle/base.py

    r7918 r8215  
    66 
    77import os 
     8import datetime 
     9import time 
    810 
    911from django.db.backends import BaseDatabaseWrapper, BaseDatabaseFeatures, BaseDatabaseOperations, util 
    1012from django.db.backends.oracle import query 
    11 from django.utils.datastructures import SortedDict 
    1213from django.utils.encoding import smart_str, force_unicode 
    1314 
     
    3031    uses_case_insensitive_names = True 
    3132    uses_custom_query_class = True 
    32     time_field_needs_date = True 
    3333    interprets_empty_strings_as_nulls = True 
    34     date_field_supports_time_value = False 
    3534 
    3635class DatabaseOperations(BaseDatabaseOperations): 
     
    181180    def tablespace_sql(self, tablespace, inline=False): 
    182181        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 
    183197 
    184198class DatabaseWrapper(BaseDatabaseWrapper): 
     
    246260class OracleParam(object): 
    247261    """ 
    248     Wrapper object for formatting parameters for Oracle. If the string  
    249     representation of the value is large enough (greater than 4000 characters)  
     262    Wrapper object for formatting parameters for Oracle. If the string 
     263    representation of the value is large enough (greater than 4000 characters) 
    250264    the input size needs to be set as NCLOB. Alternatively, if the parameter has 
    251     an `input_size` attribute, then the value of the `input_size` attribute will  
     265    an `input_size` attribute, then the value of the `input_size` attribute will 
    252266    be used instead. Otherwise, no input size will be set for the parameter when 
    253267    executing the query. 
     
    283297        else: 
    284298            return tuple([OracleParam(p, self.charset, True) for p in params]) 
    285      
     299 
    286300    def _guess_input_sizes(self, params_list): 
    287301        if isinstance(params_list[0], dict): 
     
    304318        else: 
    305319            return [p.smart_str for p in params] 
    306          
     320 
    307321    def execute(self, query, params=None): 
    308322        if params is None: 
  • django/branches/gis/django/db/backends/oracle/query.py

    r7523 r8215  
    8888            included in the query. 
    8989            """ 
     90 
    9091            # The `do_offset` flag indicates whether we need to construct 
    9192            # the SQL needed to use limit/offset w/Oracle. 
    92             do_offset = with_limits and (self.high_mark or self.low_mark) 
     93            do_offset = with_limits and (self.high_mark is not None 
     94                                         or self.low_mark) 
    9395 
    9496            # If no offsets, just return the result of the base class 
     
    118120            # extra selection SQL. 
    119121            self.extra_select['rn'] = 'ROW_NUMBER() OVER (ORDER BY %s )' % rn_orderby 
    120             sql, params= super(OracleQuery, self).as_sql(with_limits=False, 
     122            sql, params = super(OracleQuery, self).as_sql(with_limits=False, 
    121123                    with_col_aliases=True) 
    122124 
     
    127129            # Place WHERE condition on `rn` for the desired range. 
    128130            result.append('WHERE rn > %d' % self.low_mark) 
    129             if self.high_mark
     131            if self.high_mark is not None
    130132                result.append('AND rn <= %d' % self.high_mark) 
    131133 
     
    149151    _classes[QueryClass] = OracleQuery 
    150152    return OracleQuery 
    151  
  • django/branches/gis/django/db/backends/sqlite3/base.py

    r7979 r8215  
    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 
    8793class DatabaseWrapper(BaseDatabaseWrapper): 
    8894    features = DatabaseFeatures() 
     
    160166    except (ValueError, TypeError): 
    161167        return None 
    162     return str(getattr(dt, lookup_type)
     168    return getattr(dt, lookup_type
    163169 
    164170def _sqlite_date_trunc(lookup_type, dt): 
  • django/branches/gis/django/db/backends/util.py

    r7279 r8215  
    11import datetime 
    2 import md5 
    32from time import time 
     3 
     4from django.utils.hashcompat import md5_constructor 
    45 
    56try: 
     
    115116        return name 
    116117 
    117     hash = md5.md5(name).hexdigest()[:4] 
     118    hash = md5_constructor(name).hexdigest()[:4] 
    118119 
    119120    return '%s%s' % (name[:length-4], hash) 
     121 
     122def format_number(value, max_digits, decimal_places): 
     123    """ 
     124    Formats a number into a string with the requisite number of digits and 
     125    decimal places. 
     126    """ 
     127    return u"%.*f" % (decimal_places, value) 
  • django/branches/gis/django/db/models/base.py

    r7979 r8215  
    1313from django.core import validators 
    1414from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError 
    15 from django.db.models.fields import AutoField, ImageField, FieldDoesNotExist 
     15from django.db.models.fields import AutoField, ImageField 
    1616from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField 
    1717from django.db.models.query import delete_objects, Q, CollectedObjects 
     
    2121from django.db.models.loading import register_models, get_model 
    2222from django.dispatch import dispatcher 
    23 from django.utils.datastructures import SortedDict 
    2423from django.utils.functional import curry 
    2524from django.utils.encoding import smart_str, force_unicode, smart_unicode 
     
    202201 
    203202        for field in fields_iter: 
     203            rel_obj = None 
    204204            if kwargs: 
    205205                if isinstance(field.rel, ManyToOneRel): 
     
    218218                        if rel_obj is None and field.null: 
    219219                            val = None 
    220                         else: 
    221                             try: 
    222                                 val = getattr(rel_obj, field.rel.get_related_field().attname) 
    223                             except AttributeError: 
    224                                 raise TypeError("Invalid value: %r should be a %s instance, not a %s" % 
    225                                     (field.name, field.rel.to, type(rel_obj))) 
    226220                else: 
    227221                    val = kwargs.pop(field.attname, field.get_default()) 
    228222            else: 
    229223                val = field.get_default() 
    230             setattr(self, field.attname, val) 
     224            # If we got passed a related instance, set it using the field.name 
     225            # instead of field.attname (e.g. "user" instead of "user_id") so 
     226            # that the object gets properly cached (and type checked) by the 
     227            # RelatedObjectDescriptor. 
     228            if rel_obj: 
     229                setattr(self, field.name, rel_obj) 
     230            else: 
     231                setattr(self, field.attname, val) 
    231232 
    232233        if kwargs: 
     
    300301        if not raw: 
    301302            for parent, field in meta.parents.items(): 
     303                # At this point, parent's primary key field may be unknown 
     304                # (for example, from administration form which doesn't fill 
     305                # this field). If so, fill it. 
     306                if getattr(self, parent._meta.pk.attname) is None and getattr(self, field.attname) is not None: 
     307                    setattr(self, parent._meta.pk.attname, getattr(self, field.attname)) 
     308 
    302309                self.save_base(raw, parent) 
    303310                setattr(self, field.attname, self._get_pk_val(parent._meta)) 
     
    473480 
    474481    def _save_FIELD_file(self, field, filename, raw_field, save=True): 
    475         directory = field.get_directory_name() 
    476         try: # Create the date-based directory if it doesn't exist. 
    477             os.makedirs(os.path.join(settings.MEDIA_ROOT, directory)) 
    478         except OSError: # Directory probably already exists. 
    479             pass 
     482        # Create the upload directory if it doesn't already exist 
     483        directory = os.path.join(settings.MEDIA_ROOT, field.get_directory_name()) 
     484        if not os.path.exists(directory): 
     485            os.makedirs(directory) 
     486        elif not os.path.isdir(directory): 
     487            raise IOError('%s exists and is not a directory' % directory)         
    480488 
    481489        # Check for old-style usage (files-as-dictionaries). Warn here first 
     
    495503            import warnings 
    496504            warnings.warn( 
    497                 message = "Representing uploaded files as dictionaries is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.", 
     505                message = "Representing uploaded files as strings is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.", 
    498506                category = DeprecationWarning, 
    499507                stacklevel = 2 
  • django/branches/gis/django/db/models/fields/__init__.py

    r8002 r8215  
    2323from django.utils.translation import ugettext_lazy, ugettext as _ 
    2424from django.utils.encoding import smart_unicode, force_unicode, smart_str 
    25 from django.utils.maxlength import LegacyMaxlength 
    2625from django.utils import datetime_safe 
    2726 
     
    6362 
    6463class Field(object): 
    65     # Provide backwards compatibility for the maxlength attribute and 
    66     # argument for this class and all subclasses. 
    67     __metaclass__ = LegacyMaxlength 
    68  
    6964    # Designates whether empty strings fundamentally are allowed at the 
    7065    # database level. 
     
    192187        self.name = name 
    193188        self.attname, self.column = self.get_attname_column() 
    194         self.verbose_name = self.verbose_name or (name and name.replace('_', ' ')) 
     189        if self.verbose_name is None and name: 
     190            self.verbose_name = name.replace('_', ' ') 
    195191 
    196192    def contribute_to_class(self, cls, name): 
     
    218214        return getattr(model_instance, self.attname) 
    219215 
     216    def get_db_prep_value(self, value): 
     217        """Returns field's value prepared for interacting with the database 
     218        backend. 
     219 
     220        Used by the default implementations of ``get_db_prep_save``and 
     221        `get_db_prep_lookup``` 
     222        """ 
     223        return value 
     224 
    220225    def get_db_prep_save(self, value): 
    221226        "Returns field's value prepared for saving into a database." 
    222         return value 
     227        return self.get_db_prep_value(value) 
    223228 
    224229    def get_db_prep_lookup(self, lookup_type, value): 
     
    227232            sql, params = value.as_sql() 
    228233            return QueryWrapper(('(%s)' % sql), params) 
    229         if lookup_type in ('exact', 'regex', 'iregex', 'gt', 'gte', 'lt', 'lte', 'month', 'day', 'search'): 
     234        if lookup_type in ('regex', 'iregex', 'month', 'day', 'search'): 
    230235            return [value] 
     236        elif lookup_type in ('exact', 'gt', 'gte', 'lt', 'lte'): 
     237            return [self.get_db_prep_value(value)] 
    231238        elif lookup_type in ('range', 'in'): 
    232             return value 
     239            return [self.get_db_prep_value(v) for v in value] 
    233240        elif lookup_type in ('contains', 'icontains'): 
    234241            return ["%%%s%%" % connection.ops.prep_for_like_query(value)] 
     
    246253            except ValueError: 
    247254                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' 
     255 
     256            if self.get_internal_type() == 'DateField': 
     257                return connection.ops.year_lookup_bounds_for_date_field(value) 
    257258            else: 
    258                 first = '%s-01-01 00:00:00' 
    259                 second = '%s-12-31 23:59:59.999999' 
    260             return [first % value, second % value] 
     259                return connection.ops.year_lookup_bounds(value) 
     260 
    261261        raise TypeError("Field has invalid lookup: %s" % lookup_type) 
    262262 
     
    289289            field_objs = [oldforms.SelectField] 
    290290 
    291             params['choices'] = self.flatchoices 
     291            params['choices'] = self.get_flatchoices() 
    292292        else: 
    293293            field_objs = self.get_manipulator_field_objs() 
     
    363363 
    364364    def get_choices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH): 
    365         "Returns a list of tuples used as SelectField choices for this field." 
     365        """Returns choices with a default blank choices included, for use 
     366        as SelectField choices for this field.""" 
    366367        first_choice = include_blank and blank_choice or [] 
    367368        if self.choices: 
     
    377378        return self.get_choices() 
    378379 
     380    def get_flatchoices(self, include_blank=True, blank_choice=BLANK_CHOICE_DASH): 
     381        "Returns flattened choices with a default blank choice included." 
     382        first_choice = include_blank and blank_choice or [] 
     383        return first_choice + list(self.flatchoices) 
     384 
    379385    def _get_val_from_obj(self, obj): 
    380386        if obj: 
     
    409415 
    410416    def _get_flatchoices(self): 
     417        """Flattened version of choices tuple.""" 
    411418        flat = [] 
    412         for choice, value in self.get_choices_default()
     419        for choice, value in self.choices
    413420            if type(value) in (list, tuple): 
    414421                flat.extend(value) 
     
    417424        return flat 
    418425    flatchoices = property(_get_flatchoices) 
    419      
     426 
    420427    def save_form_data(self, instance, data): 
    421428        setattr(instance, self.name, data) 
     
    450457            raise validators.ValidationError, _("This value must be an integer.") 
    451458 
     459    def get_db_prep_value(self, value): 
     460        if value is None: 
     461            return None 
     462        return int(value) 
     463 
    452464    def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True): 
    453465        if not rel: 
     
    478490    def __init__(self, *args, **kwargs): 
    479491        kwargs['blank'] = True 
     492        if 'default' not in kwargs and not kwargs.get('null'): 
     493            kwargs['default'] = False 
    480494        Field.__init__(self, *args, **kwargs) 
    481495 
     
    488502        if value in ('f', 'False', '0'): return False 
    489503        raise validators.ValidationError, _("This value must be either True or False.") 
     504 
     505    def get_db_prep_value(self, value): 
     506        if value is None: 
     507            return None 
     508        return bool(value) 
    490509 
    491510    def get_manipulator_field_objs(self): 
     
    550569            raise validators.ValidationError, _('Enter a valid date in YYYY-MM-DD format.') 
    551570 
    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  
    561571    def pre_save(self, model_instance, add): 
    562572        if self.auto_now or (self.auto_now_add and add): 
     
    582592            return self.editable or self.auto_now or self.auto_now_add 
    583593 
    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) 
     594    def get_db_prep_value(self, value): 
     595        # Casts dates into the format expected by the backend 
     596        return connection.ops.value_to_db_date(self.to_python(value)) 
    594597 
    595598    def get_manipulator_field_objs(self): 
     
    620623        if isinstance(value, datetime.date): 
    621624            return datetime.datetime(value.year, value.month, value.day) 
     625 
     626        # Attempt to parse a datetime: 
     627        value = smart_str(value) 
     628        # split usecs, because they are not recognized by strptime. 
     629        if '.' in value: 
     630            try: 
     631                value, usecs = value.split('.') 
     632                usecs = int(usecs) 
     633            except ValueError: 
     634                raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM[ss[.uuuuuu]] format.') 
     635        else: 
     636            usecs = 0 
     637        kwargs = {'microsecond': usecs} 
    622638        try: # Seconds are optional, so try converting seconds first. 
    623             return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6]) 
     639            return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M:%S')[:6], 
     640                                     **kwargs) 
     641 
    624642        except ValueError: 
    625643            try: # Try without seconds. 
    626                 return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5]) 
     644                return datetime.datetime(*time.strptime(value, '%Y-%m-%d %H:%M')[:5], 
     645                                         **kwargs) 
    627646            except ValueError: # Try without hour/minutes/seconds. 
    628647                try: 
    629                     return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3]) 
     648                    return datetime.datetime(*time.strptime(value, '%Y-%m-%d')[:3], 
     649                                             **kwargs) 
    630650                except ValueError: 
    631                     raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM format.') 
    632  
    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) 
     651                    raise validators.ValidationError, _('Enter a valid date/time in YYYY-MM-DD HH:MM[ss[.uuuuuu]] format.') 
     652 
     653    def get_db_prep_value(self, value): 
     654        # Casts dates into the format expected by the backend 
     655        return connection.ops.value_to_db_datetime(self.to_python(value)) 
    649656 
    650657    def get_manipulator_field_objs(self): 
     
    711718        decimal places. 
    712719        """ 
    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 
    720  
    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) 
     720        # Method moved to django.db.backends.util. 
     721        # 
     722        # It is preserved because it is used by the oracle backend 
     723        # (django.db.backends.oracle.query), and also for 
     724        # backwards-compatibility with any external code which may have used 
     725        # this method. 
     726        from django.db.backends import util 
     727        return util.format_number(value, self.max_digits, self.decimal_places) 
     728 
     729    def get_db_prep_value(self, value): 
     730        return connection.ops.value_to_db_decimal(self.to_python(value), 
     731                self.max_digits, self.decimal_places) 
    733732 
    734733    def get_manipulator_field_objs(self): 
     
    769768        return "FileField" 
    770769 
    771     def get_db_prep_save(self, value): 
     770    def get_db_prep_value(self, value): 
    772771        "Returns field's value prepared for saving into a database." 
    773772        # Need to convert UploadedFile objects provided via a form to unicode for database insertion 
     
    910909    empty_strings_allowed = False 
    911910 
     911    def get_db_prep_value(self, value): 
     912        if value is None: 
     913            return None 
     914        return float(value) 
     915 
    912916    def get_manipulator_field_objs(self): 
    913917        return [oldforms.FloatField] 
     
    957961class IntegerField(Field): 
    958962    empty_strings_allowed = False 
     963    def get_db_prep_value(self, value): 
     964        if value is None: 
     965            return None 
     966        return int(value) 
     967 
    959968    def get_manipulator_field_objs(self): 
    960969        return [oldforms.IntegerField] 
     
    10041013        raise validators.ValidationError, _("This value must be either None, True or False.") 
    10051014 
     1015    def get_db_prep_value(self, value): 
     1016        if value is None: 
     1017            return None 
     1018        return bool(value) 
     1019 
    10061020    def get_manipulator_field_objs(self): 
    10071021        return [oldforms.NullBooleanField] 
     
    10161030        return super(NullBooleanField, self).formfield(**defaults) 
    10171031 
    1018 class PhoneNumberField(IntegerField): 
     1032class PhoneNumberField(Field): 
    10191033    def get_manipulator_field_objs(self): 
    10201034        return [oldforms.PhoneNumberField] 
     
    10981112        return "TimeField" 
    10991113 
    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) 
    1107         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) 
     1114    def to_python(self, value): 
     1115        if value is None: 
     1116            return None 
     1117        if isinstance(value, datetime.time): 
     1118            return value 
     1119 
     1120        # Attempt to parse a datetime: 
     1121        value = smart_str(value) 
     1122        # split usecs, because they are not recognized by strptime. 
     1123        if '.' in value: 
     1124            try: 
     1125                value, usecs = value.split('.') 
     1126                usecs = int(usecs) 
     1127            except ValueError: 
     1128                raise validators.ValidationError, _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.') 
     1129        else: 
     1130            usecs = 0 
     1131        kwargs = {'microsecond': usecs} 
     1132 
     1133        try: # Seconds are optional, so try converting seconds first. 
     1134            return datetime.time(*time.strptime(value, '%H:%M:%S')[3:6], 
     1135                                 **kwargs) 
     1136        except ValueError: 
     1137            try: # Try without seconds. 
     1138                return datetime.time(*time.strptime(value, '%H:%M')[3:5], 
     1139                                         **kwargs) 
     1140            except ValueError: 
     1141                raise validators.ValidationError, _('Enter a valid time in HH:MM[:ss[.uuuuuu]] format.') 
    11141142 
    11151143    def pre_save(self, model_instance, add): 
     
    11211149            return super(TimeField, self).pre_save(model_instance, add) 
    11221150 
    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) 
     1151    def get_db_prep_value(self, value): 
     1152        # Casts times into the format expected by the backend 
     1153        return connection.ops.value_to_db_time(self.to_python(value)) 
    11401154 
    11411155    def get_manipulator_field_objs(self): 
  • django/branches/gis/django/db/models/fields/related.py

    <
    r8002 r8215  
    33from django.db.models.fields import AutoField, Field, IntegerField, PositiveIntegerField, PositiveSmallIntegerField, FieldDoesNotExist 
    44from django.db.models.related import RelatedObject 
     5from django.db.models.query import QuerySet 
    56from django.db.models.query_utils import QueryWrapper 
    6 from django.utils.text import capfirst 
    77from django.utils.translation import ugettext_lazy, string_concat, ungettext, ugettext as _ 
    88from django.utils.functional import curry 
    9 from django.utils.encoding import smart_unicode 
    109from django.core import validators 
    1110from django import oldforms 
     
    2524pending_lookups = {} 
    2625 
    27 def add_lazy_relation(cls, field, relation): 
     26def add_lazy_relation(cls, field, relation, operation): 
    2827    """ 
    2928    Adds a lookup on ``cls`` when a related field is defined using a string, 
     
    4746    lazy relationships -- then the relation won't be set up until the 
    4847    class_prepared signal fires at the end of model initialization. 
     48     
     49    operation is the work that must be performed once the relation can be resolved. 
    4950    """ 
    5051    # Check for recursive relations 
     
    6869    model = get_model(app_label, model_name, False) 
    6970    if model: 
    70         field.rel.to = model 
    71         field.do_related_class(model, cls) 
     71        operation(field, model, cls) 
    7272    else: 
    7373        key = (app_label, model_name) 
    74         value = (cls, field
     74        value = (cls, field, operation
    7575        pending_lookups.setdefault(key, []).append(value) 
    7676 
     
    8080    """ 
    8181    key = (sender._meta.app_label, sender.__name__) 
    82     for cls, field in pending_lookups.pop(key, []): 
    83         field.rel.to = sender 
    84         field.do_related_class(sender, cls) 
     82    for cls, field, operation in pending_lookups.pop(key, []): 
     83        operation(field, sender, cls) 
    8584 
    8685dispatcher.connect(do_pending_lookups, signal=signals.class_prepared) 
     
    110109        other = self.rel.to 
    111110        if isinstance(other, basestring): 
    112             add_lazy_relation(cls, self, other) 
     111            def resolve_related_class(field, model, cls): 
     112                field.rel.to = model 
     113                field.do_related_class(model, cls) 
     114            add_lazy_relation(cls, self, other, resolve_related_class) 
    113115        else: 
    114116            self.do_related_class(other, cls) 
     
    116118    def set_attributes_from_rel(self): 
    117119        self.name = self.name or (self.rel.to._meta.object_name.lower() + '_' + self.rel.to._meta.pk.name) 
    118         self.verbose_name = self.verbose_name or self.rel.to._meta.verbose_name 
     120        if self.verbose_name is None: 
     121            self.verbose_name = self.rel.to._meta.verbose_name 
    119122        self.rel.field_name = self.rel.field_name or self.rel.to._meta.pk.name 
    120123 
     
    237240            else: 
    238241                params = {'%s__exact' % self.field.rel.field_name: val} 
    239             rel_obj = self.field.rel.to._default_manager.get(**params) 
     242 
     243            # If the related manager indicates that it should be used for 
     244            # related fields, respect that. 
     245            rel_mgr = self.field.rel.to._default_manager 
     246            if getattr(rel_mgr, 'use_for_related_fields', False): 
     247                rel_obj = rel_mgr.get(**params) 
     248            else: 
     249                rel_obj = QuerySet(self.field.rel.to).get(**params) 
    240250            setattr(instance, cache_name, rel_obj) 
    241251            return rel_obj 
     
    341351        manager.add(*value) 
    342352 
    343 def create_many_related_manager(superclass): 
     353def create_many_related_manager(superclass, through=False): 
    344354    """Creates a manager that subclasses 'superclass' (which is a Manager) 
    345355    and adds behavior for many-to-many related objects.""" 
     
    355365