Django

Code

Changeset 4151

Show
Ignore:
Timestamp:
12/04/06 12:04:55 (2 years ago)
Author:
jpellerin
Message:

[multi-db] Merge trunk to [3875]. Some tests still failing.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/multiple-db-support/AUTHORS

    r4142 r4151  
    6565    crankycoder@gmail.com 
    6666    Matt Croydon <http://www.postneo.com/> 
     67    dackze+django@gmail.com 
    6768    Jonathan Daugherty (cygnus) <http://www.cprogrammer.org/> 
    6869    Jason Davies (Esaj) <http://www.jasondavies.com/> 
     
    105106    Jeong-Min Lee 
    106107    Christopher Lenz <http://www.cmlenz.net/> 
     108    lerouxb@gmail.com 
    107109    limodou 
     110    mattmcc 
    108111    Martin Maney <http://www.chipy.org/Martin_Maney> 
    109112    Manuzhai 
     
    117120    Robin Munn <http://www.geekforgod.com/> 
    118121    Nebojša Dorđević 
     122    Fraser Nevett <mail@nevett.org> 
    119123    Sam Newman <http://www.magpiebrain.com/> 
    120124    Neal Norwitz <nnorwitz@google.com> 
     
    144148    Swaroop C H <http://www.swaroopch.info> 
    145149    Aaron Swartz <http://www.aaronsw.com/> 
     150    Tyson Tate <tyson@fallingbullets.com> 
    146151    Tom Tobin 
    147152    Tom Insam 
  • django/branches/multiple-db-support/django/bin/daily_cleanup.py

    r2809 r4151  
    1 "Daily cleanup file" 
     1""" 
     2Daily cleanup job. 
     3 
     4Can be run as a cronjob to clean out old data from the database (only expired 
     5sessions at the moment). 
     6""" 
    27 
    38from django.db import backend, connection, transaction 
    4  
    5 DOCUMENTATION_DIRECTORY = '/home/html/documentation/' 
    69 
    710def clean_up(): 
     
    912    cursor = connection.cursor() 
    1013    cursor.execute("DELETE FROM %s WHERE %s < NOW()" % \ 
    11         (backend.quote_name('core_sessions'), backend.quote_name('expire_date'))) 
    12     cursor.execute("DELETE FROM %s WHERE %s < NOW() - INTERVAL '1 week'" % \ 
    13         (backend.quote_name('registration_challenges'), backend.quote_name('request_date'))) 
     14        (backend.quote_name('django_session'), backend.quote_name('expire_date'))) 
    1415    transaction.commit_unless_managed() 
    1516 
  • django/branches/multiple-db-support/django/contrib/admin/templates/admin_doc/view_detail.html

    r3355 r4151  
    99<h1>{{ name }}</h1> 
    1010 
    11 <h2 class="subhead">{{ summary|escape }}</h2> 
     11<h2 class="subhead">{{ summary }}</h2> 
    1212 
    1313<p>{{ body }}</p> 
  • django/branches/multiple-db-support/django/contrib/auth/create_superuser.py

    r2841 r4151  
    4747                sys.stderr.write("Error: That username is invalid. Use only letters, digits and underscores.\n") 
    4848                username = None 
     49                continue 
    4950            try: 
    5051                User.objects.get(username=username) 
  • django/branches/multiple-db-support/django/contrib/auth/forms.py

    r4142 r4151  
    55from django.core import validators 
    66from django import forms 
    7 from django.utils.translation import gettext_lazy as _ 
    87 
    98class UserCreationForm(forms.Manipulator): 
  • django/branches/multiple-db-support/django/contrib/sitemaps/templates/sitemap_index.xml

    r3712 r4151  
    11<?xml version="1.0" encoding="UTF-8"?> 
    22<sitemapindex xmlns="http://www.google.com/schemas/sitemap/0.84"> 
    3 {% for location in sitemaps %} 
    4         <sitemap> 
    5                 <loc>{{ location|escape }}</loc> 
    6         </sitemap> 
    7 {% endfor %} 
     3{% for location in sitemaps %}<sitemap><loc>{{ location|escape }}</loc></sitemap>{% endfor %} 
    84</sitemapindex> 
  • django/branches/multiple-db-support/django/contrib/sitemaps/templates/sitemap.xml

    r3712 r4151  
    11<?xml version="1.0" encoding="UTF-8"?> 
    22<urlset xmlns="http://www.google.com/schemas/sitemap/0.84"> 
     3{% spaceless %} 
    34{% for url in urlset %} 
    45  <url> 
     
    910   </url> 
    1011{% endfor %} 
     12{% endspaceless %} 
    1113</urlset> 
  • django/branches/multiple-db-support/django/core/handlers/base.py

    r3427 r4151  
    4949                self._exception_middleware.insert(0, mw_instance.process_exception) 
    5050 
    51     def get_response(self, path, request): 
     51    def get_response(self, request): 
    5252        "Returns an HttpResponse object for the given HttpRequest" 
    5353        from django.core import exceptions, urlresolvers 
     
    6363        resolver = urlresolvers.RegexURLResolver(r'^/', settings.ROOT_URLCONF) 
    6464        try: 
    65             callback, callback_args, callback_kwargs = resolver.resolve(path) 
     65            callback, callback_args, callback_kwargs = resolver.resolve(request.path) 
    6666 
    6767            # Apply view middleware 
     
    106106                receivers = dispatcher.send(signal=signals.got_request_exception) 
    107107                # When DEBUG is False, send an error message to the admins. 
    108                 subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), getattr(request, 'path', '')
     108                subject = 'Error (%s IP): %s' % ((request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS and 'internal' or 'EXTERNAL'), request.path
    109109                try: 
    110110                    request_repr = repr(request) 
  • django/branches/multiple-db-support/django/core/handlers/modpython.py

    r4141 r4151  
    103103                'SCRIPT_NAME':       None, # Not supported 
    104104                'SERVER_NAME':       self._req.server.server_hostname, 
    105                 'SERVER_PORT':       self._req.server.port
     105                'SERVER_PORT':       str(self._req.connection.local_addr[1])
    106106                'SERVER_PROTOCOL':   self._req.protocol, 
    107107                'SERVER_SOFTWARE':   'mod_python' 
     
    151151        try: 
    152152            request = ModPythonRequest(req) 
    153             response = self.get_response(req.uri, request) 
     153            response = self.get_response(request) 
    154154 
    155155            # Apply response middleware 
  • django/branches/multiple-db-support/django/core/handlers/wsgi.py

    r4141 r4151  
    7575        self.environ = environ 
    7676        self.path = environ['PATH_INFO'] 
    77         self.META = environ  
     77        self.META = environ 
    7878        self.method = environ['REQUEST_METHOD'].upper() 
    7979 
     
    187187        try: 
    188188            request = WSGIRequest(environ) 
    189             response = self.get_response(request.path, request
     189            response = self.get_response(request
    190190 
    191191            # Apply response middleware 
  • django/branches/multiple-db-support/django/core/management.py

    r4142 r4151  
    670670    Returns number of errors. 
    671671    """ 
    672     from django.db import models, model_connection_name 
     672    from django.conf import settings 
     673    from django.db import connections, models, model_connection_name 
    673674    from django.db.models.loading import get_app_errors 
    674675    from django.db.models.fields.related import RelatedObject 
     
    682683        opts = cls._meta 
    683684        connection_name = model_connection_name(cls) 
     685        connection = connections[connection_name] 
    684686         
    685687        # Do field-specific validation. 
     
    712714            if f.db_index not in (None, True, False): 
    713715                e.add(opts, '"%s": "db_index" should be either None, True or False.' % f.name) 
     716 
     717            # Check that maxlength <= 255 if using older MySQL versions. 
     718            if settings.DATABASE_ENGINE == 'mysql': 
     719                db_version = connection.connection.get_server_version() 
     720                if db_version < (5, 0, 3) and isinstance(f, (models.CharField, models.CommaSeparatedIntegerField, models.SlugField)) and f.maxlength > 255: 
     721                    e.add(opts, '"%s": %s cannot have a "maxlength" greater than 255 when you are using a version of MySQL prior to 5.0.3 (you are using %s).' % (f.name, f.__class__.__name__, '.'.join([str(n) for n in db_version[:3]]))) 
    714722 
    715723            # Check to see if the related field will clash with any 
  • django/branches/multiple-db-support/django/db/backends/mysql/base.py

    r4127 r4151  
    1414from MySQLdb.constants import FIELD_TYPE 
    1515import types 
     16import re 
    1617 
    1718DatabaseError = Database.DatabaseError 
     
    2425    FIELD_TYPE.TIME: util.typecast_time, 
    2526}) 
     27 
     28# This should match the numerical portion of the version numbers (we can treat 
     29# versions like 5.0.24 and 5.0.24a as the same). Based on the list of version 
     30# at http://dev.mysql.com/doc/refman/4.1/en/news.html and 
     31# http://dev.mysql.com/doc/refman/5.0/en/news.html . 
     32server_version_re = re.compile(r'(\d{1,2})\.(\d{1,2})\.(\d{1,2})') 
    2633 
    2734# This is an extra debug layer over MySQL queries, to display warnings. 
     
    5764        self.connection = None 
    5865        self.queries = [] 
     66        self.server_version = None 
    5967 
    6068    def _valid_connection(self): 
     
    106114            self.connection.close() 
    107115            self.connection = None 
     116 
     117    def get_server_version(self): 
     118        if not self.server_version: 
     119            if not self._valid_connection(): 
     120                self.cursor() 
     121            m = server_version_re.match(self.connection.get_server_info()) 
     122            if not m: 
     123                raise Exception('Unable to determine MySQL version from version string %r' % self.connection.get_server_info()) 
     124            self.server_version = tuple([int(x) for x in m.groups()]) 
     125        return self.server_version 
    108126 
    109127supports_constraints = True 
  • django/branches/multiple-db-support/django/db/models/fields/__init__.py

    r4142 r4151  
    66from django.core.exceptions import ObjectDoesNotExist 
    77from django.utils.functional import curry 
     8from django.utils.itercompat import tee 
    89from django.utils.text import capfirst 
    910from django.utils.translation import gettext, gettext_lazy 
     
    8182        self.unique_for_date, self.unique_for_month = unique_for_date, unique_for_month 
    8283        self.unique_for_year = unique_for_year 
    83         self.choices = choices or [] 
     84        self._choices = choices or [] 
    8485        self.radio_admin = radio_admin 
    8586        self.help_text = help_text 
     
    324325    def bind(self, fieldmapping, original, bound_field_class): 
    325326        return bound_field_class(self, fieldmapping, original) 
     327 
     328    def _get_choices(self): 
     329        if hasattr(self._choices, 'next'): 
     330            choices, self._choices = tee(self._choices) 
     331            return choices 
     332        else: 
     333            return self._choices 
     334    choices = property(_get_choices) 
    326335 
    327336class AutoField(Field): 
  • django/branches/multiple-db-support/django/db/models/manipulators.py

    r4142 r4151  
    178178 
    179179                        if f == related.field: 
    180                             param = getattr(new_object, related.field.rel.field_name) 
     180                            param = getattr(new_object, related.field.rel.get_related_field().attname) 
    181181                        elif (not self.change) and isinstance(f, AutoField): 
    182182                            param = None 
     
    216216                        for f in related.opts.many_to_many: 
    217217                            if child_follow.get(f.name, None) and not f.rel.edit_inline: 
    218                                 setattr(new_rel_obj, f.name, f.rel.to.objects.filter(pk__in=rel_new_data[f.attname])) 
     218                                new_value = rel_new_data[f.attname] 
     219                                if f.rel.raw_id_admin: 
     220                                    new_value = new_value[0] 
     221                                setattr(new_rel_obj, f.name, f.rel.to.objects.filter(pk__in=new_value)) 
    219222                                if self.change: 
    220223                                    self.fields_changed.append('%s for %s "%s"' % (f.verbose_name, related.opts.verbose_name, new_rel_obj)) 
     
    301304    else: 
    302305        raise validators.ValidationError, _("%(object)s with this %(type)s already exists for the given %(field)s.") % \ 
    303             {'object': capfirst(opts.verbose_name), 'type': field_list[0].verbose_name, 'field': get_text_list(field_name_list[1:], 'and')} 
     306            {'object': capfirst(opts.verbose_name), 'type': field_list[0].verbose_name, 'field': get_text_list([f.verbose_name for f in field_list[1:]], 'and')} 
    304307 
    305308def manipulator_validator_unique_for_date(from_field, date_field, opts, lookup_type, self, field_data, all_data): 
  • django/branches/multiple-db-support/django/middleware/common.py

    r4142 r4151  
    33from django.core.mail import mail_managers 
    44import md5 
     5import re 
    56 
    67class CommonMiddleware(object): 
     
    6263                domain = http.get_host(request) 
    6364                referer = request.META.get('HTTP_REFERER', None) 
    64                 is_internal = referer and (domain in referer) 
     65                is_internal = _is_internal_request(domain, referer) 
    6566                path = request.get_full_path() 
    6667                if referer and not _is_ignorable_404(path) and (is_internal or '?' not in referer): 
     
    8990            return True 
    9091    return False 
     92 
     93def _is_internal_request(domain, referer): 
     94    "Return true if the referring URL is the same domain as the current request" 
     95    # Different subdomains are treated as different domains. 
     96    return referer is not None and re.match("^https?://%s/" % re.escape(domain), referer) 
  • django/branches/multiple-db-support/django/template/__init__.py

    r3739 r4151  
    533533                if i18n_arg: 
    534534                    args.append((False, _(i18n_arg.replace(r'\"', '"')))) 
    535                 elif constant_arg
     535                elif constant_arg is not None
    536536                    args.append((False, constant_arg.replace(r'\"', '"'))) 
    537537                elif var_arg: 
  • django/branches/multiple-db-support/django/test/client.py

    r3739 r4151  
    99class ClientHandler(BaseHandler): 
    1010    """ 
    11     A HTTP Handler that can be used for testing purposes.  
     11    A HTTP Handler that can be used for testing purposes. 
    1212    Uses the WSGI interface to compose requests, but returns 
    1313    the raw HttpResponse object 
     
    2525        try: 
    2626            request = WSGIRequest(environ) 
    27             response = self.get_response(request.path, request
     27            response = self.get_response(request
    2828 
    2929            # Apply response middleware 
     
    3333        finally: 
    3434            dispatcher.send(signal=signals.request_finished) 
    35          
     35 
    3636        return response 
    3737 
     
    4545    A simple method for encoding multipart POST data from a dictionary of 
    4646    form values. 
    47      
     47 
    4848    The key will be used as the form data name; the value will be transmitted 
    4949    as content. If the value is a file, the contents of the file will be sent 
     
    7070                str(value) 
    7171            ]) 
    72          
     72 
    7373    lines.extend([ 
    7474        '--' + boundary + '--', 
     
    7979class Client: 
    8080    """ 
    81     A class that can act as a client for testing purposes.  
    82        
     81    A class that can act as a client for testing purposes. 
     82 
    8383    It allows the user to compose GET and POST requests, and 
    8484    obtain the response that the server gave to those requests. 
     
    8989    Client objects are stateful - they will retain cookie (and 
    9090    thus session) details for the lifetime of the Client instance. 
    91      
     91 
    9292    This is not intended as a replacement for Twill/Selenium or 
    9393    the like - it is here to allow testing against the 
     
    9999        self.defaults = defaults 
    100100        self.cookie = SimpleCookie() 
    101          
     101 
    102102    def request(self, **request): 
    103103        """ 
    104         The master request method. Composes the environment dictionary  
     104        The master request method. Composes the environment dictionary 
    105105        and passes to the handler, returning the result of the handler. 
    106106        Assumes defaults for the query environment, which can be overridden 
     
    113113            'QUERY_STRING':      '', 
    114114            'REQUEST_METHOD':    'GET', 
    115             'SCRIPT_NAME':       None,  
     115            'SCRIPT_NAME':       None, 
    116116            'SERVER_NAME':       'testserver', 
    117117            'SERVER_PORT':       80, 
    118118            'SERVER_PROTOCOL':   'HTTP/1.1', 
    119         }         
     119        } 
    120120        environ.update(self.defaults) 
    121         environ.update(request)         
     121        environ.update(request) 
    122122 
    123123        # Curry a data dictionary into an instance of 
     
    126126        on_template_render = curry(store_rendered_templates, data) 
    127127        dispatcher.connect(on_template_render, signal=signals.template_rendered) 
    128          
     128 
    129129        response = self.handler(environ) 
    130          
     130 
    131131        # Add any rendered template detail to the response 
    132         # If there was only one template rendered (the most likely case),  
     132        # If there was only one template rendered (the most likely case), 
    133133        # flatten the list to a single element 
    134134        for detail in ('template', 'context'): 
     
    140140            else: 
    141141                setattr(response, detail, None) 
    142          
     142 
    143143        if response.cookies: 
    144144            self.cookie.update(response.cookies) 
    145145 
    146146        return response 
    147          
     147 
    148148    def get(self, path, data={}, **extra): 
    149149        "Request a response from the server using GET." 
     
    156156        } 
    157157        r.update(extra) 
    158          
     158 
    159159        return self.request(**r) 
    160      
     160 
    161161    def post(self, path, data={}, **extra): 
    162162        "Request a response from the server using POST." 
    163          
     163 
    164164        BOUNDARY = 'BoUnDaRyStRiNg' 
    165165 
     
    174174        } 
    175175        r.update(extra) 
    176          
     176 
    177177        return self.request(**r) 
    178178 
     
    181181        A specialized sequence of GET and POST to log into a view that 
    182182        is protected by a @login_required access decorator. 
    183          
     183 
    184184        path should be the URL of the page that is login protected. 
    185          
    186         Returns the response from GETting the requested URL after  
     185 
     186        Returns the response from GETting the requested URL after 
    187187        login is complete. Returns False if login process failed. 
    188188        """ 
    189         # First, GET the page that is login protected.  
     189        # First, GET the page that is login protected. 
    190190        # This page will redirect to the login page. 
    191191        response = self.get(path) 
    192192        if response.status_code != 302: 
    193193            return False 
    194              
     194 
    195195        login_path, data = response['Location'].split('?') 
    196196        next = data.split('=')[1] 
     
    200200        if response.status_code != 200: 
    201201            return False 
    202              
     202 
    203203        # Last, POST the login data. 
    204204        form_data = { 
  • django/branches/multiple-db-support/docs/faq.txt

    r3712 r4151  
    314314.. _`SQLite 3`: http://www.sqlite.org/ 
    315315 
     316Do I lose anything by using Python 2.3 versus newer Python versions, such as Python 2.5? 
     317---------------------------------------------------------------------------------------- 
     318 
     319No. Django itself is guaranteed to work with any version of Python from 2.3 
     320and higher. 
     321 
     322If you use a Python version newer than 2.3, you will, of course, be able to 
     323take advantage of newer Python features in your own code, along with the speed 
     324improvements and other optimizations that have been made to the Python language 
     325itself. But the Django framework itself should work equally well on 2.3 as it 
     326does on 2.4 or 2.5. 
     327 
    316328Do I have to use mod_python? 
    317329---------------------------- 
  • django/branches/multiple-db-support/docs/templates_python.txt

    r4139 r4151  
    367367you'll have to activate it. 
    368368 
     369Writing your own context processors 
     370~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
     371 
     372A context processor has a very simple interface: It's just a Python function 
     373that takes one argument, an ``HttpRequest`` object, and returns a dictionary 
     374that gets added to the template context. Each context processor *must* return 
     375a dictionary. 
     376 
     377Custom context processors can live anywhere in your code base. All Django cares 
     378about is that your custom context processors are pointed-to by your 
     379``TEMPLATE_CONTEXT_PROCESSORS`` setting. 
     380 
    369381Loading templates 
    370382----------------- 
  • django/branches/multiple-db-support/tests/regressiontests/dateformat/tests.py

    r3712 r4151  
    2222>>> format(my_birthday, 'N') 
    2323'July' 
    24 >>> format(my_birthday, 'O') 
    25 '+0100' 
     24>>> no_tz or format(my_birthday, 'O') == '+0100' 
     25True 
    2626>>> format(my_birthday, 'P') 
    2727'10 p.m.' 
    28 >>> format(my_birthday, 'r') 
    29 'Sun, 8 Jul 1979 22:00:00 +0100' 
     28>>> no_tz or format(my_birthday, 'r') == 'Sun, 8 Jul 1979 22:00:00 +0100' 
     29True 
    3030>>> format(my_birthday, 's') 
    3131'00' 
     
    3434>>> format(my_birthday, 't') 
    3535'31' 
    36 >>> format(my_birthday, 'T') 
    37 'CET' 
    38 >>> format(my_birthday, 'U') 
    39 '300531600' 
     36>>> no_tz or format(my_birthday, 'T') == 'CET' 
     37True 
     38>>> no_tz or format(my_birthday, 'U') == '300531600' 
     39True 
    4040>>> format(my_birthday, 'w') 
    4141'0' 
     
    4848>>> format(my_birthday, 'z') 
    4949'189' 
    50 >>> format(my_birthday, 'Z') 
    51 '3600' 
     50>>> no_tz or format(my_birthday, 'Z') == '3600' 
     51True 
    5252 
    53 >>> format(summertime, 'I') 
    54 '1' 
    55 >>> format(summertime, 'O') 
    56 '+0200' 
    57 >>> format(wintertime, 'I') 
    58 '0' 
    59 >>> format(wintertime, 'O') 
    60 '+0100' 
     53>>> no_tz or format(summertime, 'I') == '1' 
     54True 
     55>>> no_tz or format(summertime, 'O') == '+0200' 
     56True 
     57>>> no_tz or format(wintertime, 'I') == '0' 
     58True 
     59>>> no_tz or format(wintertime, 'O') == '+0100' 
     60True 
    6161 
    6262>>> format(my_birthday, r'Y z \C\E\T') 
     
    7474translation.activate('en-us') 
    7575 
    76 time.tzset() 
     76try: 
     77    time.tzset() 
     78    no_tz = False 
     79except AttributeError: 
     80    no_tz = True 
    7781 
    7882my_birthday = datetime.datetime(1979, 7, 8, 22, 00) 
  • django/branches/multiple-db-support/tests/regressiontests/templates/tests.py

    r4139 r4151  
    170170            # Escaped backslash using known escape char 
    171171            'basic-syntax35': (r'{{ var|default_if_none:"foo\now" }}', {"var": None}, r'foo\now'), 
     172 
     173            # Empty strings can be passed as arguments to filters 
     174            'basic-syntax36': (r'{{ var|join:"" }}', {'var': ['a', 'b', 'c']}, 'abc'), 
    172175 
    173176            ### COMMENT TAG ###########################################################