|
1 """ |
|
2 Caching framework. |
|
3 |
|
4 This package defines set of cache backends that all conform to a simple API. |
|
5 In a nutshell, a cache is a set of values -- which can be any object that |
|
6 may be pickled -- identified by string keys. For the complete API, see |
|
7 the abstract BaseCache class in django.core.cache.backends.base. |
|
8 |
|
9 Client code should not access a cache backend directly; instead it should |
|
10 either use the "cache" variable made available here, or it should use the |
|
11 get_cache() function made available here. get_cache() takes a backend URI |
|
12 (e.g. "memcached://127.0.0.1:11211/") and returns an instance of a backend |
|
13 cache class. |
|
14 |
|
15 See docs/cache.txt for information on the public API. |
|
16 """ |
|
17 |
|
18 from cgi import parse_qsl |
|
19 from django.conf import settings |
|
20 from django.core import signals |
|
21 from django.core.cache.backends.base import InvalidCacheBackendError |
|
22 from django.utils import importlib |
|
23 |
|
24 # Name for use in settings file --> name of module in "backends" directory. |
|
25 # Any backend scheme that is not in this dictionary is treated as a Python |
|
26 # import path to a custom backend. |
|
27 BACKENDS = { |
|
28 'memcached': 'memcached', |
|
29 'locmem': 'locmem', |
|
30 'file': 'filebased', |
|
31 'db': 'db', |
|
32 'dummy': 'dummy', |
|
33 } |
|
34 |
|
35 def parse_backend_uri(backend_uri): |
|
36 """ |
|
37 Converts the "backend_uri" into a cache scheme ('db', 'memcached', etc), a |
|
38 host and any extra params that are required for the backend. Returns a |
|
39 (scheme, host, params) tuple. |
|
40 """ |
|
41 if backend_uri.find(':') == -1: |
|
42 raise InvalidCacheBackendError, "Backend URI must start with scheme://" |
|
43 scheme, rest = backend_uri.split(':', 1) |
|
44 if not rest.startswith('//'): |
|
45 raise InvalidCacheBackendError, "Backend URI must start with scheme://" |
|
46 |
|
47 host = rest[2:] |
|
48 qpos = rest.find('?') |
|
49 if qpos != -1: |
|
50 params = dict(parse_qsl(rest[qpos+1:])) |
|
51 host = rest[2:qpos] |
|
52 else: |
|
53 params = {} |
|
54 if host.endswith('/'): |
|
55 host = host[:-1] |
|
56 |
|
57 return scheme, host, params |
|
58 |
|
59 def get_cache(backend_uri): |
|
60 scheme, host, params = parse_backend_uri(backend_uri) |
|
61 if scheme in BACKENDS: |
|
62 name = 'django.core.cache.backends.%s' % BACKENDS[scheme] |
|
63 else: |
|
64 name = scheme |
|
65 module = importlib.import_module(name) |
|
66 return getattr(module, 'CacheClass')(host, params) |
|
67 |
|
68 cache = get_cache(settings.CACHE_BACKEND) |
|
69 |
|
70 # Some caches -- pythont-memcached in particular -- need to do a cleanup at the |
|
71 # end of a request cycle. If the cache provides a close() method, wire it up |
|
72 # here. |
|
73 if hasattr(cache, 'close'): |
|
74 signals.request_finished.connect(cache.close) |
|
75 |