-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathPKG-INFO
More file actions
301 lines (240 loc) · 13.4 KB
/
PKG-INFO
File metadata and controls
301 lines (240 loc) · 13.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
Metadata-Version: 1.1
Name: cache-dependencies
Version: 0.7.7.48
Summary: Cache-dependencies (former Cache-tagging) allows you easily invalidate all cache records tagged with a given tag(s). Supports Django.
Home-page: https://bitbucket.org/emacsway/cache-dependencies
Author: Ivan Zakrevsky
Author-email: ivzak@yandex.ru
License: BSD License
Description: ============================================
Cache Dependencies (with support for Django)
============================================
Cache-dependencies (former Cache-tagging) allows you easily invalidate all cache records tagged with a given tag(s). Supports Django.
Tags are a way to categorize cache records.
When you save a cache, you can set a list of tags to apply for this record.
Then you will be able to invalidate all cache records tagged with a given tag (or tags).
Cache tagging allows to manage cached values and easily link them to Model signals.
* Home Page: https://bitbucket.org/emacsway/cache-dependencies
* Docs: https://cache-dependencies.readthedocs.io/
* Browse source code (canonical repo): https://bitbucket.org/emacsway/cache-dependencies/src
* GitHub mirror: https://github.com/emacsway/cache-dependencies
* Get source code (canonical repo): ``hg clone https://bitbucket.org/emacsway/cache-dependencies``
* Get source code (mirror): ``git clone https://github.com/emacsway/cache-dependencies.git``
* PyPI: https://pypi.python.org/pypi/cache-dependencies
LICENSE:
* License is BSD
Usage with Django
==================
project settings.py::
INSTALLED_APPS = (
# ...
'django_cache_dependencies',
# ...
)
project urls.py::
from django_cache_dependencies import autodiscover
autodiscover()
application example::
# Default backend
from django_cache_dependencies import caches
cache = caches['default']
value = cache.get('cache_name')
if value is None:
value = get_value_func()
cache.set('cache_name', value, tags=(
'blog.post',
'categories.category.pk:{0}'.format(obj.category_id),
))
manual invalidation::
from django_cache_dependencies import caches
cache = caches['default']
# ...
cache.invalidate_tags('tag1', 'tag2', 'tag3')
# or
tag_list = ['tag1', 'tag2', 'tag3', ]
cache.invalidate_tags(*tag_list)
Ancestors automatically receive tags from their descendants.
You do not have to worry about how to pass the tags from fragment's caches
to the composite (parent) cache. It is done automatically::
val1 = cache.get('name1')
if val1 is None:
val2 = cache.get('name2')
if val2 is None:
val2 = get_val2()
cache.set('name2', val2, ('tag2', ), 120)
val1 = get_val1() + val2
cache.set('name1', val1, ('tag1', ), 120)
cache.invalidate_tags('tag2')
assert cache.get('name2') is None
assert cache.get('name1') is None # cache with name 'name1' was invalidated
# by tag 'tag2' of descendant.
You can turn off this logic::
# turn off for cache instance
cache.ignore_descendants = True
# turn off for get template
cache.get('cachename', abort=True)
# abort cache creating
val = cache.get('cachename')
if val is None:
try:
val = get_val()
except Exception:
cache.abort('cachename')
appname.caches.py file::
# Variant 1. Using registry.register().
# Each item from list creates model's post_save and pre_delete signal.
# Func takes changed model and returns list of tags.
# When the signal is called, it gets varied tags and deletes all caches with this tags.
# Inside the handler function available all local variables from signal.
# Or only object. Of your choice.
from django_cache_dependencies import registry, caches
from models import Post
from news import Article
cache_handlers = [
#(model, func, [cache_alias, ]),
(Post, lambda *a, **kw: ("blog.post.pk:{0}".format(kw['instance'].pk), ), 'my_cache_alias'),
(Article, lambda obj: (
"news.alticle.pk:{0}".format(obj.pk),
"categories.category.pk:{0}.blog.type.pk:{1}".format(obj.category_id, obj.type_id), # Composite tag
"news.alticle"
)),
]
registry.register(cache_handlers)
# Variant 2. Low-lewel. Using signals for invalidation.
from django_cache_dependencies import registry
from models import Post
from django.db.models.signals import post_save, post_delete
def invalidation_callback(sender, instance, **kwars):
cache.invalidate_tags(
'tag1', 'tag2', 'blog.post.pk:{1}'.format(instance.pk)
)
post_save.connect(invalidation_callback, sender=Post)
pre_delete.connect(invalidation_callback, sender=Post)
template::
{% load cache_tagging_tags %}
{% cache_tagging 'cache_name' 'categories.category.pk:15' 'blog.post' tags=tag_list_from_view timeout=3600 %}
...
{% cache_add_tags 'new_tag1' %}
...
{% cache_add_tags 'new_tag2' 'new_tag3' %}
...
{% if do_not_cache_condition %}
{% cache_tagging_prevent %}
{% endif %}
{% end_cache_tagging %}
{% comment %}
{% cache_tagging cache_name [tag1] [tag2] ... [tags=tag_list] [timeout=3600] %}
{% cache_add_tags tag_or_list_of_tags %}
If context has attribute "request", then templatetag {% cache_tagging %}
adds to request a new attribute "cache_tagging" (instance of set() object) with all tags.
If request already has attribute "cache_tagging", and it's instance of set() object,
then templatetag {% cache_tagging %} adds all tags to this object.
You can use together templatetag {% cache_tagging %} and decorator @cache_page().
In this case, when @cache_page() decorator will save response,
it will also adds all tags from request.cache_tagging to cache.
You need not worry about it.
If need, you can prevent caching by templatetag {% cache_tagging_prevent %}.
In this case also will be prevented @cache_page() decorator, if it's used,
and context has attribute "request".
{% endcomment %}
Support for `django-phased <https://github.com/codysoyland/django-phased>`_::
{% comment %}
Support for django-phased https://github.com/codysoyland/django-phased
See documentation for more details https://django-phased.readthedocs.io/
{% endcomment %}
{% load cache_tagging_tags %}
{% load phased_tags %}
{% cache_tagging 'cache_name' 'categories.category.pk:15' 'blog.post' tags=tag_list_from_view timeout=3600 phased=1 %}
... Cached fragment here ...
{% phased with comment_count object %}
{# Non-cached fragment here. #}
There are {{ comment_count }} comments for "{{ object }}".
{% endphased %}
{% end_cache_tagging %}
nocache support::
{% load cache_tagging_tags %}
{% cache_tagging 'cache_name' 'categories.category.pk:15' 'blog.post' tags=tag_list_from_view timeout=3600 nocache=1 %}
... Cached fragment here ...
{% nocache %}
"""
Non-cached fragment here. Just python code.
Why nocache, if exists django-phased?
Because template engine agnostic. We can use not only Django templates.
Of course, for only Django template engine, django-phased is the best option.
"""
if request.user.is_authenticated():
echo('Hi, ', filters.escape(request.user.username), '!')
echo(render_to_string('user_menu.html', context))
else:
echo(render_to_string('login_menu.html', context))
{% endnocache %}
{% end_cache_tagging %}
view decorator::
from django_cache_dependencies.decorators import cache_page
# See also useful decorator to bind view's args and kwargs to request
# https://bitbucket.org/emacsway/django-ext/src/d8b55d86680e/django_ext/middleware/view_args_to_request.py
@cache_page(3600, tags=lambda request: ('blog.post', ) + get_tags_for_request(request))
def cached_view(request):
result = get_result()
return HttpResponse(result)
How about transaction and multithreading (multiprocessing)?::
from django.db import transaction
from django_cache_dependencies import cache
from django_cache_dependencies import cache_transaction
with cache.transaction, transaction.commit_on_success():
# ... some code
# Changes a some data
cache.invalidate_tags('tag1', 'tag2', 'tag3')
# ... some long code
# Another concurrent process/thread can obtain old data at this time,
# after changes but before commit, and create cache with old data,
# if isolation level is not "Read uncommitted".
# Otherwise, if isolation level is "Read uncommitted", and transaction will rollback,
# the concurrent and current process/thread can creates cache with dirty data.
Transaction handler as decorator::
from django.db import transaction
from django_cache_dependencies import cache
from django_cache_dependencies.decorators import cache_transaction
@cache.transaction
@transaction.commit_on_success():
def some_view(request):
# ... some code
cache.invalidate_tags('tag1', 'tag2', 'tag3')
# ... some long code
# Another concurrent process/thread can obtain old data at this time,
# after changes but before commit, and create cache with old data,
# if isolation level is not "Read uncommitted".
# Otherwise, if isolation level is "Read uncommitted", and transaction will rollback,
# the concurrent and current process/thread can creates cache with dirty data.
#
# We can even invalidate cache before data changes,
# by signals django.db.models.signals.pre_save()
# or django.db.models.signals.pre_delete(), and don't worry.
Transaction handler as middleware::
MIDDLEWARE_CLASSES = [
# ...
"django_cache_dependencies.middleware.TransactionMiddleware", # Should be before
"django.middleware.transaction.TransactionMiddleware",
# ...
]
Forked from https://github.com/Harut/django-cachecontrol
See also articles:
- "`About problems of cache invalidation. Cache tagging. <https://emacsway.github.io/en/cache-dependencies/>`_"
- "`О проблемах инвалидации кэша. Тегирование кэша. <https://emacsway.github.io/ru/cache-dependencies/>`_"
Keywords: django cache dependencies tagging
Platform: UNKNOWN
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Web Environment
Classifier: Framework :: Django
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.2
Classifier: Programming Language :: Python :: 3.3
Classifier: Programming Language :: Python :: 3.4
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
Classifier: Topic :: Software Development :: Libraries :: Python Modules