Ticket #17258: 17258.thread-local-connections.diff

File 17258.thread-local-connections.diff, 4.8 KB (added by Julien Phalip, 12 years ago)
  • django/db/__init__.py

    diff --git a/django/db/__init__.py b/django/db/__init__.py
    index 8395468..e3fcbbd 100644
    a b  
     1from threading import local
    12from django.conf import settings
    23from django.core import signals
    34from django.core.exceptions import ImproperlyConfigured
    router = ConnectionRouter(settings.DATABASE_ROUTERS)  
    2425# by the PostgreSQL backends.
    2526# we load all these up for backwards compatibility, you should use
    2627# connections['default'] instead.
    27 connection = connections[DEFAULT_DB_ALIAS]
     28class DefaultConnectionProxy(local):
     29    """
     30    Thread-local proxy for the default connection.
     31    """
     32    def __getattr__(self, item):
     33        return getattr(connections[DEFAULT_DB_ALIAS], item)
     34    def __setattr__(self, name, value):
     35        return setattr(connections[DEFAULT_DB_ALIAS], name, value)
     36connection = DefaultConnectionProxy()
    2837backend = load_backend(connection.settings_dict['ENGINE'])
    2938
    3039# Register an event that closes the database connection
  • django/db/backends/__init__.py

    diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
    index f2bde84..0f4fc31 100644
    a b try:  
    22    import thread
    33except ImportError:
    44    import dummy_thread as thread
    5 from threading import local
    65from contextlib import contextmanager
    76
    87from django.conf import settings
    from django.utils.importlib import import_module  
    1312from django.utils.timezone import is_aware
    1413
    1514
    16 class BaseDatabaseWrapper(local):
     15class BaseDatabaseWrapper(object):
    1716    """
    1817    Represents a database connection.
    1918    """
  • django/db/utils.py

    diff --git a/django/db/utils.py b/django/db/utils.py
    index f0c13e3..41ad6df 100644
    a b  
    11import os
     2from threading import local
    23
    34from django.conf import settings
    45from django.core.exceptions import ImproperlyConfigured
    class ConnectionDoesNotExist(Exception):  
    5051class ConnectionHandler(object):
    5152    def __init__(self, databases):
    5253        self.databases = databases
    53         self._connections = {}
     54        self._connections = local()
    5455
    5556    def ensure_defaults(self, alias):
    5657        """
    class ConnectionHandler(object):  
    7374            conn.setdefault(setting, None)
    7475
    7576    def __getitem__(self, alias):
    76         if alias in self._connections:
    77             return self._connections[alias]
     77        if hasattr(self._connections, alias):
     78            return getattr(self._connections, alias)
    7879
    7980        self.ensure_defaults(alias)
    8081        db = self.databases[alias]
    8182        backend = load_backend(db['ENGINE'])
    8283        conn = backend.DatabaseWrapper(db, alias)
    83         self._connections[alias] = conn
     84        setattr(self._connections, alias, conn)
    8485        return conn
    8586
     87    def __setitem__(self, key, value):
     88        setattr(self._connections, key, value)
     89
    8690    def __iter__(self):
    8791        return iter(self.databases)
    8892
  • tests/regressiontests/backends/tests.py

    diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py
    index 936f010..be83a9a 100644
    a b  
    33from __future__ import with_statement, absolute_import
    44
    55import datetime
     6import threading
    67
    78from django.conf import settings
    89from django.core.management.color import no_style
    class FkConstraintsTests(TransactionTestCase):  
    446447                        connection.check_constraints()
    447448            finally:
    448449                transaction.rollback()
     450
     451class ThreadTests(TestCase):
     452
     453    def test_default_connection_thread_local(self):
     454        """
     455        Ensure that the default connection (i.e. django.db.connection) is
     456        different for each thread.
     457        Refs #17258.
     458        """
     459        connections_set = set()
     460        connection.cursor()
     461        connections_set.add(connection.connection)
     462        def runner():
     463            from django.db import connection
     464            connection.cursor()
     465            connections_set.add(connection.connection)
     466        for x in xrange(2):
     467            t = threading.Thread(target=runner)
     468            t.start()
     469            t.join()
     470        self.assertEquals(len(connections_set), 3)
     471
     472    def test_connections_thread_local(self):
     473        """
     474        Ensure that the connections are different for each thread.
     475        Refs #17258.
     476        """
     477        connections_set = set()
     478        for conn in connections.all():
     479            connections_set.add(conn)
     480        def runner():
     481            from django.db import connections
     482            for conn in connections.all():
     483                connections_set.add(conn)
     484        for x in xrange(2):
     485            t = threading.Thread(target=runner)
     486            t.start()
     487            t.join()
     488        self.assertEquals(len(connections_set), 6)
     489 No newline at end of file
Back to Top