blob: 81d468f218fbe1d24803e2a15bf45a73bb21e434 [file] [log] [blame]
showard09096d82008-07-07 23:20:49 +00001from django.db import connection as django_connection
2from django.conf import settings
3from django.dispatch import dispatcher
4from django.core import signals
5
6class ReadOnlyConnection(object):
7 """
8 This class constructs a new connection to the DB using the read-only
9 credentials from settings. It reaches into some internals of
10 django.db.connection which are undocumented as far as I know, but I believe
11 it works across many, if not all, of the backends.
12 """
13 def __init__(self):
14 self._connection = None
15
16
17 def _open_connection(self):
18 if self._connection is not None:
19 return
20 self._save_django_state()
21 self._connection = self._get_readonly_connection()
22 self._restore_django_state()
23
24
25 def _save_django_state(self):
26 self._old_connection = django_connection.connection
showard1a573ca2008-09-11 01:32:03 +000027 self._old_host = settings.DATABASE_HOST
showard09096d82008-07-07 23:20:49 +000028 self._old_username = settings.DATABASE_USER
29 self._old_password = settings.DATABASE_PASSWORD
30
31
32 def _restore_django_state(self):
33 django_connection.connection = self._old_connection
showard1a573ca2008-09-11 01:32:03 +000034 settings.DATABASE_HOST = self._old_host
showard09096d82008-07-07 23:20:49 +000035 settings.DATABASE_USER = self._old_username
36 settings.DATABASE_PASSWORD = self._old_password
37
38
39 def _get_readonly_connection(self):
showard1a573ca2008-09-11 01:32:03 +000040 settings.DATABASE_HOST = settings.DATABASE_READONLY_HOST
showard09096d82008-07-07 23:20:49 +000041 settings.DATABASE_USER = settings.DATABASE_READONLY_USER
42 settings.DATABASE_PASSWORD = settings.DATABASE_READONLY_PASSWORD
43 django_connection.connection = None
44 # cursor() causes a new connection to be created
45 cursor = django_connection.cursor()
46 assert django_connection.connection is not None
47 return django_connection.connection
48
49
50 def set_django_connection(self):
51 assert (django_connection.connection != self._connection or
52 self._connection is None)
53 self._open_connection()
54 self._old_connection = django_connection.connection
55 django_connection.connection = self._connection
56
57
58 def unset_django_connection(self):
59 assert self._connection is not None
60 assert django_connection.connection == self._connection
61 django_connection.connection = self._old_connection
62
63
64 def cursor(self):
65 self._open_connection()
66 return self._connection.cursor()
67
68
69 def close(self):
70 if self._connection is not None:
71 assert django_connection != self._connection
72 self._connection.close()
73 self._connection = None
74
75
76connection = ReadOnlyConnection()
77# close any open connection when request finishes
78dispatcher.connect(connection.close, signal=signals.request_finished)