blob: 19ac51e2c6b64a6cc6da11b24a9e92a091a41427 [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
27 self._old_username = settings.DATABASE_USER
28 self._old_password = settings.DATABASE_PASSWORD
29
30
31 def _restore_django_state(self):
32 django_connection.connection = self._old_connection
33 settings.DATABASE_USER = self._old_username
34 settings.DATABASE_PASSWORD = self._old_password
35
36
37 def _get_readonly_connection(self):
38 settings.DATABASE_USER = settings.DATABASE_READONLY_USER
39 settings.DATABASE_PASSWORD = settings.DATABASE_READONLY_PASSWORD
40 django_connection.connection = None
41 # cursor() causes a new connection to be created
42 cursor = django_connection.cursor()
43 assert django_connection.connection is not None
44 return django_connection.connection
45
46
47 def set_django_connection(self):
48 assert (django_connection.connection != self._connection or
49 self._connection is None)
50 self._open_connection()
51 self._old_connection = django_connection.connection
52 django_connection.connection = self._connection
53
54
55 def unset_django_connection(self):
56 assert self._connection is not None
57 assert django_connection.connection == self._connection
58 django_connection.connection = self._old_connection
59
60
61 def cursor(self):
62 self._open_connection()
63 return self._connection.cursor()
64
65
66 def close(self):
67 if self._connection is not None:
68 assert django_connection != self._connection
69 self._connection.close()
70 self._connection = None
71
72
73connection = ReadOnlyConnection()
74# close any open connection when request finishes
75dispatcher.connect(connection.close, signal=signals.request_finished)