13 try: |
12 try: |
14 # Most of the time, the database backend will be one of the official |
13 # Most of the time, the database backend will be one of the official |
15 # backends that ships with Django, so look there first. |
14 # backends that ships with Django, so look there first. |
16 _import_path = 'django.db.backends.' |
15 _import_path = 'django.db.backends.' |
17 backend = __import__('%s%s.base' % (_import_path, settings.DATABASE_ENGINE), {}, {}, ['']) |
16 backend = __import__('%s%s.base' % (_import_path, settings.DATABASE_ENGINE), {}, {}, ['']) |
18 creation = __import__('%s%s.creation' % (_import_path, settings.DATABASE_ENGINE), {}, {}, ['']) |
|
19 except ImportError, e: |
17 except ImportError, e: |
20 # If the import failed, we might be looking for a database backend |
18 # If the import failed, we might be looking for a database backend |
21 # distributed external to Django. So we'll try that next. |
19 # distributed external to Django. So we'll try that next. |
22 try: |
20 try: |
23 _import_path = '' |
21 _import_path = '' |
24 backend = __import__('%s.base' % settings.DATABASE_ENGINE, {}, {}, ['']) |
22 backend = __import__('%s.base' % settings.DATABASE_ENGINE, {}, {}, ['']) |
25 creation = __import__('%s.creation' % settings.DATABASE_ENGINE, {}, {}, ['']) |
|
26 except ImportError, e_user: |
23 except ImportError, e_user: |
27 # The database backend wasn't found. Display a helpful error message |
24 # The database backend wasn't found. Display a helpful error message |
28 # listing all possible (built-in) database backends. |
25 # listing all possible (built-in) database backends. |
29 backend_dir = os.path.join(__path__[0], 'backends') |
26 backend_dir = os.path.join(__path__[0], 'backends') |
30 available_backends = [f for f in os.listdir(backend_dir) if not f.startswith('_') and not f.startswith('.') and not f.endswith('.py') and not f.endswith('.pyc')] |
27 try: |
|
28 available_backends = [f for f in os.listdir(backend_dir) if not f.startswith('_') and not f.startswith('.') and not f.endswith('.py') and not f.endswith('.pyc')] |
|
29 except EnvironmentError: |
|
30 available_backends = [] |
31 available_backends.sort() |
31 available_backends.sort() |
32 if settings.DATABASE_ENGINE not in available_backends: |
32 if settings.DATABASE_ENGINE not in available_backends: |
33 raise ImproperlyConfigured, "%r isn't an available database backend. Available options are: %s" % \ |
33 raise ImproperlyConfigured, "%r isn't an available database backend. Available options are: %s\nError was: %s" % \ |
34 (settings.DATABASE_ENGINE, ", ".join(map(repr, available_backends))) |
34 (settings.DATABASE_ENGINE, ", ".join(map(repr, available_backends)), e_user) |
35 else: |
35 else: |
36 raise # If there's some other error, this must be an error in Django itself. |
36 raise # If there's some other error, this must be an error in Django itself. |
37 |
|
38 def _import_database_module(import_path='', module_name=''): |
|
39 """Lazily import a database module when requested.""" |
|
40 return __import__('%s%s.%s' % (import_path, settings.DATABASE_ENGINE, module_name), {}, {}, ['']) |
|
41 |
|
42 # We don't want to import the introspect module unless someone asks for it, so |
|
43 # lazily load it on demmand. |
|
44 get_introspection_module = curry(_import_database_module, _import_path, 'introspection') |
|
45 |
|
46 def get_creation_module(): |
|
47 return creation |
|
48 |
|
49 # We want runshell() to work the same way, but we have to treat it a |
|
50 # little differently (since it just runs instead of returning a module like |
|
51 # the above) and wrap the lazily-loaded runshell() method. |
|
52 runshell = lambda: _import_database_module(_import_path, "client").runshell() |
|
53 |
37 |
54 # Convenient aliases for backend bits. |
38 # Convenient aliases for backend bits. |
55 connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS) |
39 connection = backend.DatabaseWrapper(**settings.DATABASE_OPTIONS) |
56 DatabaseError = backend.DatabaseError |
40 DatabaseError = backend.DatabaseError |
57 IntegrityError = backend.IntegrityError |
41 IntegrityError = backend.IntegrityError |
58 |
42 |
59 # Register an event that closes the database connection |
43 # Register an event that closes the database connection |
60 # when a Django request is finished. |
44 # when a Django request is finished. |
61 dispatcher.connect(connection.close, signal=signals.request_finished) |
45 def close_connection(**kwargs): |
|
46 connection.close() |
|
47 signals.request_finished.connect(close_connection) |
62 |
48 |
63 # Register an event that resets connection.queries |
49 # Register an event that resets connection.queries |
64 # when a Django request is started. |
50 # when a Django request is started. |
65 def reset_queries(): |
51 def reset_queries(**kwargs): |
66 connection.queries = [] |
52 connection.queries = [] |
67 dispatcher.connect(reset_queries, signal=signals.request_started) |
53 signals.request_started.connect(reset_queries) |
68 |
54 |
69 # Register an event that rolls back the connection |
55 # Register an event that rolls back the connection |
70 # when a Django request has an exception. |
56 # when a Django request has an exception. |
71 def _rollback_on_exception(): |
57 def _rollback_on_exception(**kwargs): |
72 from django.db import transaction |
58 from django.db import transaction |
73 transaction.rollback_unless_managed() |
59 try: |
74 dispatcher.connect(_rollback_on_exception, signal=signals.got_request_exception) |
60 transaction.rollback_unless_managed() |
|
61 except DatabaseError: |
|
62 pass |
|
63 signals.got_request_exception.connect(_rollback_on_exception) |