|
0
|
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: |
|
29
|
42 |
raise InvalidCacheBackendError("Backend URI must start with scheme://") |
|
0
|
43 |
scheme, rest = backend_uri.split(':', 1) |
|
|
44 |
if not rest.startswith('//'): |
|
29
|
45 |
raise InvalidCacheBackendError("Backend URI must start with scheme://") |
|
0
|
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 |
|