缓存依赖项(以前的缓存标记)允许您轻松地使用给定标记标记的所有缓存记录失效。支持Django。

cache-dependencies的Python项目详细描述


缓存依赖项(以前的缓存标记)允许您轻松地使用给定标记标记的所有缓存记录失效。支持Django。

标记是对缓存记录进行分类的一种方法。 保存缓存时,可以设置要应用于此记录的标记列表。 然后,您将能够使使用给定标记(或多个标记)标记的所有缓存记录失效。

缓存标记允许管理缓存值并轻松将其链接到模型信号。

许可证:

  • 许可证是BSD

与django一起使用

项目设置.py:

INSTALLED_APPS = (
    # ...
    'django_cache_dependencies',
    # ...
)

项目URL.py:

from django_cache_dependencies import autodiscover
autodiscover()

应用示例:

# 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),
    ))

手动失效:

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)

祖先自动从其后代接收标记。 您不必担心如何从片段的缓存中传递标记 到复合(父)缓存。自动完成:

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.

您可以关闭此逻辑:

# 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文件:

# 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)

模板:

{% 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 %}

支持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支持:

{% 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 %}

视图装饰器:

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)

事务和多线程(多处理)怎么样?:

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.

作为装饰器的事务处理程序:

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.

作为中间件的事务处理程序:

MIDDLEWARE_CLASSES = [
    # ...
    "django_cache_dependencies.middleware.TransactionMiddleware",  # Should be before
    "django.middleware.transaction.TransactionMiddleware",
    # ...
]

https://github.com/Harut/django-cachecontrol分叉

另请参阅文章:

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java如何修复尝试将用户签名到服务器主机时出现的“字符串无法转换为json对象”错误?   控制台Java:不使用新行更新命令行中的文本   java servlet接收xml数据时,出现错误   使用REST API在Bitbucket中复制或复制存储库   java如何在JavaFX中对齐一行?   java如何在活动中显示通过服务获得的数据?   返回BigDecimal作为字符串:返回int   java组织。openqa。硒。InvalidSelectorException:尝试查找元素时选择器无效   java仅在阻塞状态下通知和通知所有影响线程   java JBOSS无法启动部署   java方法的返回值能保证类型安全吗?   JavaeShadoop序列化组织。阿帕奇。hadoop。木卫一。短写失败   java如果我在同一个类上同步了两个方法,它们能同时运行吗?   不使用java数据库的spring分页实现   java如何将字符串切碎成这样的数组?