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/core/cache/backends/base.py

    r6815 r8215  
    6464        return self.get(key) is not None 
    6565 
    66     __contains__ = has_key 
     66    def __contains__(self, key): 
     67        """ 
     68        Returns True if the key is in the cache and has not expired. 
     69        """ 
     70        # This is a separate method, rather than just a copy of has_key(), 
     71        # so that it always has the same functionality as has_key(), even 
     72        # if a subclass overrides it. 
     73        return self.has_key(key) 
  • django/branches/gis/django/core/cache/backends/filebased.py

    r6920 r8215  
    11"File-based cache backend" 
    22 
    3 import md5 
    4 import os, time 
     3import os 
     4import time 
    55try: 
    66    import cPickle as pickle 
    77except ImportError: 
    88    import pickle 
     9 
    910from django.core.cache.backends.base import BaseCache 
     11from django.utils.hashcompat import md5_constructor 
    1012 
    1113class CacheClass(BaseCache): 
    1214    def __init__(self, dir, params): 
    1315        BaseCache.__init__(self, params) 
    14          
     16 
    1517        max_entries = params.get('max_entries', 300) 
    1618        try: 
     
    1820        except (ValueError, TypeError): 
    1921            self._max_entries = 300 
    20              
     22 
    2123        cull_frequency = params.get('cull_frequency', 3) 
    2224        try: 
     
    2426        except (ValueError, TypeError): 
    2527            self._cull_frequency = 3 
    26              
     28 
    2729        self._dir = dir 
    2830        if not os.path.exists(self._dir): 
     
    3234        if self.has_key(key): 
    3335            return None 
    34          
     36 
    3537        self.set(key, value, timeout) 
    3638 
     
    5355        fname = self._key_to_file(key) 
    5456        dirname = os.path.dirname(fname) 
    55          
     57 
    5658        if timeout is None: 
    5759            timeout = self.default_timeout 
    58              
     60 
    5961        self._cull() 
    60          
     62 
    6163        try: 
    6264            if not os.path.exists(dirname): 
     
    104106        if int(self._num_entries) < self._max_entries: 
    105107            return 
    106          
     108 
    107109        try: 
    108110            filelist = os.listdir(self._dir) 
    109111        except (IOError, OSError): 
    110112            return 
    111          
     113 
    112114        if self._cull_frequency == 0: 
    113115            doomed = filelist 
     
    134136        bits of the path into directory prefixes to be nice to filesystems 
    135137        that have problems with large numbers of files in a directory. 
    136          
     138 
    137139        Thus, a cache key of "foo" gets turnned into a file named 
    138140        ``{cache-dir}ac/bd/18db4cc2f85cedef654fccc4a4d8``. 
    139141        """ 
    140         path = md5.new(key.encode('utf-8')).hexdigest() 
     142        path = md5_constructor(key.encode('utf-8')).hexdigest() 
    141143        path = os.path.join(path[:2], path[2:4], path[4:]) 
    142144        return os.path.join(self._dir, path) 
     
    148150        return count 
    149151    _num_entries = property(_get_num_entries) 
    150  
  • django/branches/gis/django/core/cache/backends/locmem.py

    r6920 r8215  
    108108            doomed = [k for (i, k) in enumerate(self._cache) if i % self._cull_frequency == 0] 
    109109            for k in doomed: 
    110                 self.delete(k) 
     110                self._delete(k) 
    111111 
    112112    def _delete(self, key): 
  • django/branches/gis/django/core/cache/__init__.py

    r6920 r8215  
    2020from django.core.cache.backends.base import InvalidCacheBackendError 
    2121 
     22# Name for use in settings file --> name of module in "backends" directory. 
     23# Any backend scheme that is not in this dictionary is treated as a Python 
     24# import path to a custom backend. 
    2225BACKENDS = { 
    23     # name for use in settings file --> name of module in "backends" directory 
    2426    'memcached': 'memcached', 
    2527    'locmem': 'locmem', 
     
    2729    'db': 'db', 
    2830    'dummy': 'dummy', 
    29 } 
    30  
    31 DEPRECATED_BACKENDS = { 
    32     # deprecated backend --> replacement module 
    33     'simple': 'locmem', 
    3431} 
    3532 
     
    4037    if not rest.startswith('//'): 
    4138        raise InvalidCacheBackendError, "Backend URI must start with scheme://" 
    42     if scheme in DEPRECATED_BACKENDS: 
    43         import warnings 
    44         warnings.warn("'%s' backend is deprecated. Use '%s' instead." %  
    45             (scheme, DEPRECATED_BACKENDS[scheme]), DeprecationWarning) 
    46         scheme = DEPRECATED_BACKENDS[scheme] 
    47     if scheme not in BACKENDS: 
    48         raise InvalidCacheBackendError, "%r is not a valid cache backend" % scheme 
    4939 
    5040    host = rest[2:] 
     
    5848        host = host[:-1] 
    5949 
    60     cache_class = getattr(__import__('django.core.cache.backends.%s' % BACKENDS[scheme], {}, {}, ['']), 'CacheClass') 
    61     return cache_class(host, params) 
     50    if scheme in BACKENDS: 
     51        module = __import__('django.core.cache.backends.%s' % BACKENDS[scheme], {}, {}, ['']) 
     52    else: 
     53        module = __import__(scheme, {}, {}, ['']) 
     54    return getattr(module, 'CacheClass')(host, params) 
    6255 
    6356cache = get_cache(settings.CACHE_BACKEND) 
  • django/branches/gis/django/core/files/uploadedfile.py

    r7918 r8215  
    44 
    55import os 
    6 import tempfile 
    76import warnings 
    87try: 
     
    1211 
    1312from django.conf import settings 
     13 
     14from django.core.files import temp as tempfile 
    1415 
    1516__all__ = ('UploadedFile', 'TemporaryUploadedFile', 'InMemoryUploadedFile', 'SimpleUploadedFile') 
  • django/branches/gis/django/core/files/uploadhandler.py

    r7918 r8215  
    22Base file upload handler classes, and the built-in concrete subclasses 
    33""" 
    4 import os 
    5 import tempfile 
     4 
    65try: 
    76    from cStringIO import StringIO 
  • django/branches/gis/django/core/handlers/base.py

    r7979 r8215  
    44from django.core import signals 
    55from django.dispatch import dispatcher 
     6from django.utils.encoding import force_unicode 
    67 
    78class BaseHandler(object): 
     
    7475        resolver = urlresolvers.RegexURLResolver(r'^/', urlconf) 
    7576        try: 
    76             callback, callback_args, callback_kwargs = resolver.resolve(request.path) 
     77            callback, callback_args, callback_kwargs = resolver.resolve( 
     78                    request.path_info) 
    7779 
    7880            # Apply view middleware 
     
    108110                return debug.technical_404_response(request, e) 
    109111            else: 
    110                 callback, param_dict = resolver.resolve404() 
    111                 return callback(request, **param_dict) 
     112                try: 
     113                    callback, param_dict = resolver.resolve404() 
     114                    return callback(request, **param_dict) 
     115                except: 
     116                    return self.handle_uncaught_exception(request, resolver, sys.exc_info()) 
    112117        except exceptions.PermissionDenied: 
    113118            return http.HttpResponseForbidden('<h1>Permission denied</h1>') 
     
    119124            exc_info = sys.exc_info() 
    120125            receivers = dispatcher.send(signal=signals.got_request_exception, request=request) 
    121  
    122             if settings.DEBUG_PROPAGATE_EXCEPTIONS: 
    123                 raise 
    124126            return self.handle_uncaught_exception(request, resolver, exc_info) 
    125127 
     
    136138        from django.conf import settings 
    137139        from django.core.mail import mail_admins 
     140 
     141        if settings.DEBUG_PROPAGATE_EXCEPTIONS: 
     142            raise 
    138143 
    139144        if settings.DEBUG: 
     
    168173        return response 
    169174 
     175def get_script_name(environ): 
     176    """ 
     177    Returns the equivalent of the HTTP request's SCRIPT_NAME environment 
     178    variable. If Apache mod_rewrite has been used, returns what would have been 
     179    the script name prior to any rewriting (so it's the script name as seen 
     180    from the client's perspective), unless DJANGO_USE_POST_REWRITE is set (to 
     181    anything). 
     182    """ 
     183    from django.conf import settings 
     184    if settings.FORCE_SCRIPT_NAME is not None: 
     185        return force_unicode(settings.FORCE_SCRIPT_NAME) 
     186 
     187    # If Apache's mod_rewrite had a whack at the URL, Apache set either 
     188    # SCRIPT_URL or REDIRECT_URL to the full resource URL before applying any 
     189    # rewrites. Unfortunately not every webserver (lighttpd!) passes this 
     190    # information through all the time, so FORCE_SCRIPT_NAME, above, is still 
     191    # needed. 
     192    script_url = environ.get('SCRIPT_URL', u'') 
     193    if not script_url: 
     194        script_url = environ.get('REDIRECT_URL', u'') 
     195    if script_url: 
     196        return force_unicode(script_url[:-len(environ.get('PATH_INFO', ''))]) 
     197    return force_unicode(environ.get('SCRIPT_NAME', u'')) 
     198 
  • django/branches/gis/django/core/handlers/modpython.py

    r7836 r8215  
    55from django.core import signals 
    66from django.core.handlers.base import BaseHandler 
     7from django.core.urlresolvers import set_script_prefix 
    78from django.dispatch import dispatcher 
    89from django.utils import datastructures 
     
    1617    def __init__(self, req): 
    1718        self._req = req 
     19        # FIXME: This isn't ideal. The request URI may be encoded (it's 
     20        # non-normalized) slightly differently to the "real" SCRIPT_NAME 
     21        # and PATH_INFO values. This causes problems when we compute path_info, 
     22        # below. For now, don't use script names that will be subject to 
     23        # encoding/decoding. 
    1824        self.path = force_unicode(req.uri) 
     25        root = req.get_options().get('django.root', '') 
     26        self.django_root = root 
     27        # req.path_info isn't necessarily computed correctly in all 
     28        # circumstances (it's out of mod_python's control a bit), so we use 
     29        # req.uri and some string manipulations to get the right value. 
     30        if root and req.uri.startswith(root): 
     31            self.path_info = force_unicode(req.uri[len(root):]) 
     32        else: 
     33            self.path_info = self.path 
     34        if not self.path_info: 
     35            # Django prefers empty paths to be '/', rather than '', to give us 
     36            # a common start character for URL patterns. So this is a little 
     37            # naughty, but also pretty harmless. 
     38            self.path_info = u'/' 
    1939 
    2040    def __repr__(self): 
     
    101121                'CONTENT_TYPE':      self._req.content_type, # This may be wrong 
    102122                'GATEWAY_INTERFACE': 'CGI/1.1', 
    103                 'PATH_INFO':         self._req.path_info, 
     123                'PATH_INFO':         self.path_info, 
    104124                'PATH_TRANSLATED':   None, # Not supported 
    105125                'QUERY_STRING':      self._req.args, 
     
    109129                'REMOTE_USER':       self._req.user, 
    110130                'REQUEST_METHOD':    self._req.method, 
    111                 'SCRIPT_NAME':       None, # Not supported 
     131                'SCRIPT_NAME':       self.django_root, 
    112132                'SERVER_NAME':       self._req.server.server_hostname, 
    113133                'SERVER_PORT':       self._req.server.port, 
     
    154174            self.load_middleware() 
    155175 
     176        set_script_prefix(req.get_options().get('django.root', '')) 
    156177        dispatcher.send(signal=signals.request_started) 
    157178        try: 
  • django/branches/gis/django/core/handlers/wsgi.py

    r7836 r8215  
    88from django import http 
    99from django.core import signals 
    10 from django.core.handlers.base import BaseHandler 
     10from django.core.handlers import base 
     11from django.core.urlresolvers import set_script_prefix 
    1112from django.dispatch import dispatcher 
    1213from django.utils import datastructures 
     
    7576class WSGIRequest(http.HttpRequest): 
    7677    def __init__(self, environ): 
     78        script_name = base.get_script_name(environ) 
     79        path_info = force_unicode(environ.get('PATH_INFO', u'/')) 
     80        if not path_info: 
     81            # Sometimes PATH_INFO exists, but is empty (e.g. accessing 
     82            # the SCRIPT_NAME URL without a trailing slash). We really need to 
     83            # operate as if they'd requested '/'. Not amazingly nice to force 
     84            # the path like this, but should be harmless. 
     85            path_info = u'/' 
    7786        self.environ = environ 
    78         self.path = force_unicode(environ['PATH_INFO']) 
     87        self.path_info = path_info 
     88        self.path = '%s%s' % (script_name, path_info) 
    7989        self.META = environ 
     90        self.META['PATH_INFO'] = path_info 
     91        self.META['SCRIPT_NAME'] = script_name 
    8092        self.method = environ['REQUEST_METHOD'].upper() 
    8193 
     
    179191    raw_post_data = property(_get_raw_post_data) 
    180192 
    181 class WSGIHandler(BaseHandler): 
     193class WSGIHandler(base.BaseHandler): 
    182194    initLock = Lock() 
    183195    request_class = WSGIRequest 
     
    195207            self.initLock.release() 
    196208 
     209        set_script_prefix(base.get_script_name(environ)) 
    197210        dispatcher.send(signal=signals.request_started) 
    198211        try: 
  • django/branches/gis/django/core/mail.py

    r7918 r8215  
    7272def forbid_multi_line_headers(name, val): 
    7373    """Forbids multi-line headers, to prevent header injection.""" 
     74    val = force_unicode(val) 
    7475    if '\n' in val or '\r' in val: 
    7576        raise BadHeaderError("Header values can't contain newlines (got %r for header %r)" % (val, name)) 
    7677    try: 
    77         val = force_unicode(val).encode('ascii') 
     78        val = val.encode('ascii') 
    7879    except UnicodeEncodeError: 
    7980        if name.lower() in ('to', 'from', 'cc'): 
     
    8586            val = ', '.join(result) 
    8687        else: 
    87             val = Header(force_unicode(val), settings.DEFAULT_CHARSET) 
     88            val = Header(val, settings.DEFAULT_CHARSET) 
    8889    return name, val 
    8990 
     
    175176    def _send(self, email_message): 
    176177        """A helper method that does the actual sending.""" 
    177         if not email_message.to
     178        if not email_message.recipients()
    178179            return False 
    179180        try: 
  • django/branches/gis/django/core/management/commands/compilemessages.py

    r7918 r8215  
    22import sys 
    33from optparse import make_option 
    4 from django.core.management.base import BaseCommand 
    5 from django.core.management.color import no_style 
     4from django.core.management.base import BaseCommand, CommandError 
    65 
    76try: 
  • django/branches/gis/django/core/management/commands/test.py

    r7354 r8215  
    1818    def handle(self, *test_labels, **options): 
    1919        from django.conf import settings 
    20         from django.db.models import get_app, get_apps 
    2120 
    2221        verbosity = int(options.get('verbosity', 1)) 
  • django/branches/gis/django/core/management/commands/testserver.py

    r7354 r8215  
    1818 
    1919    def handle(self, *fixture_labels, **options): 
    20         from django.conf import settings 
    2120        from django.core.management import call_command 
    2221        from django.test.utils import create_test_db 
  • django/branches/gis/django/core/management/sql.py

    r7836 r8215  
    182182        opts = model._meta 
    183183        for f in opts.local_many_to_many: 
    184             if isinstance(f.rel, generic.GenericRel)
     184            if not f.creates_table
    185185                continue 
    186186            if cursor and table_name_converter(f.m2m_db_table()) in table_names: 
     
    354354    inline_references = connection.features.inline_fk_references 
    355355    for f in opts.local_many_to_many: 
    356         if not isinstance(f.rel, generic.GenericRel)
     356        if f.creates_table
    357357            tablespace = f.db_tablespace or opts.db_tablespace 
    358358            if tablespace and connection.features.supports_tablespaces:  
     
    436436 
    437437    # Post-creation SQL should come before any initial SQL data is loaded. 
    438     # However, this should not be done for fields that are part of a  
    439     # a parent model (via model inheritance). 
     438    # However, this should not be done for fields that are part of a a parent 
     439    # model (via model inheritance). 
    440440    nm = opts.init_name_map() 
    441     post_sql_fields = [f for f in opts.fields if nm[f.name][1] is None and hasattr(f, '_post_create_sql')] 
     441    post_sql_fields = [f for f in opts.local_fields if hasattr(f, 'post_create_sql')] 
    442442    for f in post_sql_fields: 
    443         output.extend(f._post_create_sql(style, model._meta.db_table)) 
     443        output.extend(f.post_create_sql(style, model._meta.db_table)) 
    444444 
    445445    # Some backends can't execute more than one SQL statement at a time, 
  • django/branches/gis/django/core/management/validation.py

    r7979 r8215  
    103103                            e.add(opts, "Reverse query name for field '%s' clashes with related field '%s.%s'. Add a related_name argument to the definition for '%s'." % (f.name, rel_opts.object_name, r.get_accessor_name(), f.name)) 
    104104 
     105        seen_intermediary_signatures = []  
    105106        for i, f in enumerate(opts.local_many_to_many): 
    106107            # Check to see if the related m2m field will clash with any 
     
    113114                if isinstance(f.rel.to, (str, unicode)): 
    114115                    continue 
    115  
     116            if getattr(f.rel, 'through', None) is not None: 
     117                if hasattr(f.rel, 'through_model'): 
     118                    from_model, to_model = cls, f.rel.to 
     119                    if from_model == to_model and f.rel.symmetrical: 
     120                        e.add(opts, "Many-to-many fields with intermediate tables cannot be symmetrical.") 
     121                    seen_from, seen_to, seen_self = False, False, 0 
     122                    for inter_field in f.rel.through_model._meta.fields: 
     123                        rel_to = getattr(inter_field.rel, 'to', None) 
     124                        if from_model == to_model: # relation to self 
     125                            if rel_to == from_model: 
     126                                seen_self += 1 
     127                            if seen_self > 2: 
     128                                e.add(opts, "Intermediary model %s has more than two foreign keys to %s, which is ambiguous and is not permitted." % (f.rel.through_model._meta.object_name, from_model._meta.object_name)) 
     129                        else: 
     130                            if rel_to == from_model: 
     131                                if seen_from: 
     132                                    e.add(opts, "Intermediary model %s has more than one foreign key to %s, which is ambiguous and is not permitted." % (f.rel.through_model._meta.object_name, rel_from._meta.object_name)) 
     133                                else: 
     134                                    seen_from = True 
     135                            elif rel_to == to_model: 
     136                                if seen_to: 
     137                                    e.add(opts, "Intermediary model %s has more than one foreign key to %s, which is ambiguous and is not permitted." % (f.rel.through_model._meta.object_name, rel_to._meta.object_name)) 
     138                                else: 
     139                                    seen_to = True 
     140                    if f.rel.through_model not in models.get_models(): 
     141                        e.add(opts, "'%s' specifies an m2m relation through model %s, which has not been installed." % (f.name, f.rel.through)) 
     142                    signature = (f.rel.to, cls, f.rel.through_model) 
     143                    if signature in seen_intermediary_signatures: 
     144                        e.add(opts, "The model %s has two manually-defined m2m relations through the model %s, which is not permitted. Please consider using an extra field on your intermediary model instead." % (cls._meta.object_name, f.rel.through_model._meta.object_name)) 
     145                    else: 
     146                        seen_intermediary_signatures.append(signature) 
     147                    seen_related_fk, seen_this_fk = False, False 
     148                    for field in f.rel.through_model._meta.fields: 
     149                        if field.rel: 
     150                            if not seen_related_fk and field.rel.to == f.rel.to: 
     151                                seen_related_fk = True 
     152                            elif field.rel.to == cls: 
     153                                seen_this_fk = True 
     154                    if not seen_related_fk or not seen_this_fk: 
     155                        e.add(opts, "'%s' has a manually-defined m2m relation through model %s, which does not have foreign keys to %s and %s" % (f.name, f.rel.through, f.rel.to._meta.object_name, cls._meta.object_name)) 
     156                else: 
     157                    e.add(opts, "'%s' specifies an m2m relation through model %s, which has not been installed" % (f.name, f.rel.through)) 
     158             
    116159            rel_opts = f.rel.to._meta 
    117160            rel_name = RelatedObject(f.rel.to, cls, f).get_accessor_name() 
  • django/branches/gis/django/core/paginator.py

    r7918 r8215  
     1from math import ceil 
     2 
    13class InvalidPage(Exception): 
    24    pass 
     
    4345        "Returns the total number of objects, across all pages." 
    4446        if self._count is None: 
    45             from django.db.models.query import QuerySet 
    46             if isinstance(self.object_list, QuerySet): 
     47            try: 
    4748                self._count = self.object_list.count() 
    48             else: 
     49            except (AttributeError, TypeError): 
     50                # AttributeError if object_list has no count() method. 
     51                # TypeError if object_list.count() requires arguments 
     52                # (i.e. is of type list). 
    4953                self._count = len(self.object_list) 
    5054        return self._count 
     
    5458        "Returns the total number of pages." 
    5559        if self._num_pages is None: 
    56             hits = self.count - 1 - self.orphans 
    57             if hits < 1: 
    58                 hits = 0 
    59             if hits == 0 and not self.allow_empty_first_page: 
     60            if self.count == 0 and not self.allow_empty_first_page: 
    6061                self._num_pages = 0 
    6162            else: 
    62                 self._num_pages = hits // self.per_page + 1 
     63                hits = max(1, self.count - self.orphans) 
     64                self._num_pages = int(ceil(hits / float(self.per_page))) 
    6365        return self._num_pages 
    6466    num_pages = property(_get_num_pages) 
     
    103105        relative to total objects in the paginator. 
    104106        """ 
     107        # Special case, return zero if no items. 
     108        if self.paginator.count == 0: 
     109            return 0 
    105110        return (self.paginator.per_page * (self.number - 1)) + 1 
    106111 
     
    110115        relative to total objects found (hits). 
    111116        """ 
     117        # Special case for the last page because there can be orphans. 
    112118        if self.number == self.paginator.num_pages: 
    113119            return self.paginator.count 
    114120        return self.number * self.paginator.per_page 
    115  
    116 class ObjectPaginator(Paginator): 
    117     """ 
    118     Legacy ObjectPaginator class, for backwards compatibility. 
    119  
    120     Note that each method on this class that takes page_number expects a 
    121     zero-based page number, whereas the new API (Paginator/Page) uses one-based 
    122     page numbers. 
    123     """ 
    124     def __init__(self, query_set, num_per_page, orphans=0): 
    125         Paginator.__init__(self, query_set, num_per_page, orphans) 
    126         import warnings 
    127         warnings.warn("The ObjectPaginator is deprecated. Use django.core.paginator.Paginator instead.", DeprecationWarning) 
    128  
    129         # Keep these attributes around for backwards compatibility. 
    130         self.query_set = query_set 
    131         self.num_per_page = num_per_page 
    132         self._hits = self._pages = None 
    133  
    134     def validate_page_number(self, page_number): 
    135         try: 
    136             page_number = int(page_number) + 1 
    137         except ValueError: 
    138             raise PageNotAnInteger 
    139         return self.validate_number(page_number) 
    140  
    141     def get_page(self, page_number): 
    142         try: 
    143             page_number = int(page_number) + 1 
    144         except ValueError: 
    145             raise PageNotAnInteger 
    146         return self.page(page_number).object_list 
    147  
    148     def has_next_page(self, page_number): 
    149         return page_number < self.pages - 1 
    150  
    151     def has_previous_page(self, page_number): 
    152         return page_number > 0 
    153  
    154     def first_on_page(self, page_number): 
    155         """ 
    156         Returns the 1-based index of the first object on the given page, 
    157         relative to total objects found (hits). 
    158         """ 
    159         page_number = self.validate_page_number(page_number) 
    160         return (self.num_per_page * (page_number - 1)) + 1 
    161  
    162     def last_on_page(self, page_number): 
    163         """ 
    164         Returns the 1-based index of the last object on the given page, 
    165         relative to total objects found (hits). 
    166         """ 
    167         page_number = self.validate_page_number(page_number) 
    168         if page_number == self.num_pages: 
    169             return self.count 
    170         return page_number * self.num_per_page 
    171  
    172     def _get_count(self): 
    173         # The old API allowed for self.object_list to be either a QuerySet or a 
    174         # list. Here, we handle both. 
    175         if self._count is None: 
    176             try: 
    177                 self._count = self.object_list.count() 
    178             except (AttributeError, TypeError): 
    179                 # AttributeError if object_list has no count() method. 
    180                 # TypeError if object_list.count() requires arguments 
    181                 # (i.e. is of type list). 
    182                 self._count = len(self.object_list) 
    183         return self._count 
    184     count = property(_get_count) 
    185  
    186     # The old API called it "hits" instead of "count". 
    187     hits = count 
    188  
    189     # The old API called it "pages" instead of "num_pages". 
    190     pages = Paginator.num_pages 
  • django/branches/gis/django/core/serializers/base.py

    r7979 r8215  
    33""" 
    44 
    5 try: 
    6     from cStringIO import StringIO 
    7 except ImportError: 
    8     from StringIO import StringIO 
     5from StringIO import StringIO 
     6 
    97from django.db import models 
    108from django.utils.encoding import smart_str, smart_unicode 
  • django/branches/gis/django/core/serializers/json.py

    r7979 r8215  
    44 
    55import datetime 
    6 from django.utils import simplejson 
     6from StringIO import StringIO 
     7 
    78from django.core.serializers.python import Serializer as PythonSerializer 
    89from django.core.serializers.python import Deserializer as PythonDeserializer 
    910from django.utils import datetime_safe 
    10 try: 
    11     from cStringIO import StringIO 
    12 except ImportError: 
    13     from StringIO import StringIO 
     11from django.utils import simplejson 
     12 
    1413try: 
    1514    import decimal 
  • django/branches/gis/django/core/serializers/pyyaml.py

    r7176 r8215  
    55""" 
    66 
     7from StringIO import StringIO 
     8import yaml 
     9 
    710from django.db import models 
    811from django.core.serializers.python import Serializer as PythonSerializer 
    912from django.core.serializers.python import Deserializer as PythonDeserializer 
    10 try: 
    11     from cStringIO import StringIO 
    12 except ImportError: 
    13     from StringIO import StringIO 
    14 import yaml 
    1513 
    1614class Serializer(PythonSerializer): 
  • django/branches/gis/django/core/urlresolvers.py

    r7836 r8215  
    77    (view_function, function_args, function_kwargs) 
    88""" 
     9 
     10import re 
    911 
    1012from django.http import Http404 
     
    1214from django.utils.encoding import iri_to_uri, force_unicode, smart_str 
    1315from django.utils.functional import memoize 
    14 import re 
     16from django.utils.thread_support import currentThread 
    1517 
    1618try: 
     
    2123_resolver_cache = {} # Maps urlconf modules to RegexURLResolver instances. 
    2224_callable_cache = {} # Maps view and url pattern names to their view functions. 
     25 
     26# SCRIPT_NAME prefixes for each thread are stored here. If there's no entry for 
     27# the current thread (which is the only one we ever access), it is assumed to 
     28# be empty. 
     29_prefixes = {} 
    2330 
    2431class Resolver404(Http404): 
     
    292299    return get_resolver(urlconf).resolve(path) 
    293300 
    294 def reverse(viewname, urlconf=None, args=None, kwargs=None): 
     301def reverse(viewname, urlconf=None, args=None, kwargs=None, prefix=None): 
    295302    args = args or [] 
    296303    kwargs = kwargs or {} 
    297     return iri_to_uri(u'/' + get_resolver(urlconf).reverse(viewname, *args, **kwargs)) 
     304    if prefix is None: 
     305        prefix = get_script_prefix() 
     306    return iri_to_uri(u'%s%s' % (prefix, get_resolver(urlconf).reverse(viewname, 
     307            *args, **kwargs))) 
    298308 
    299309def clear_url_caches(): 
     
    302312    _resolver_cache.clear() 
    303313    _callable_cache.clear() 
     314 
     315def set_script_prefix(prefix): 
     316    """ 
     317    Sets the script prefix for the current thread. 
     318    """ 
     319    if not prefix.endswith('/'): 
     320        prefix += '/' 
     321    _prefixes[currentThread()] = prefix 
     322 
     323def get_script_prefix(): 
     324    """ 
     325    Returns the currently active script prefix. Useful for client code that 
     326    wishes to construct their own URLs manually (although accessing the request 
     327    instance is normally going to be a lot cleaner). 
     328    """ 
     329    return _prefixes.get(currentThread(), u'/') 
     330