{ "info": { "author": "Mikhail Korobov", "author_email": "kmike84@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Environment :: Web Environment", "Framework :: Django", "Framework :: Django :: 1.10", "Framework :: Django :: 1.11", "Framework :: Django :: 1.8", "Framework :: Django :: 1.9", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "# django-cache-utils\n\n[![CircleCI](https://circleci.com/gh/infoscout/django-cache-utils.svg?style=svg)](https://circleci.com/gh/infoscout/django-cache-utils)\n[![codecov](https://codecov.io/gh/infoscout/django-cache-utils/branch/master/graph/badge.svg)](https://codecov.io/gh/infoscout/django-cache-utils)\n\ndjango-cache-utils provides utils for make cache-related work easier:\n\n* `cached` decorator. It can be applied to function, method or classmethod\n and can be used with any django cache backend (built-in or third-party like\n django-newcache).\n\n Supports fine-grained invalidation for exact parameter set (with any backend)\n and bulk cache invalidation (only with ``group_backend``). Cache keys are\n human-readable because they are constructed from callable's full name and\n arguments and then sanitized to make memcached happy.\n\n Wrapped callable gets ``invalidate`` methods. Call ``invalidate`` with\n same arguments as function and the cached result for these arguments will be\n invalidated.\n\n* `group_backend`. It is a django memcached cache backend with group O(1)\n invalidation ability, dog-pile effect prevention using MintCache algorythm\n and project version support to allow gracefull updates and multiple django\n projects on same memcached instance.\n Long keys (>250) are auto-truncated and appended with md5 hash.\n\n\n* `cache_utils.cache get`, `cache_utils.cache.set`, `cache_utils.delete` are wrappers\n for the standard django cache get, set, delete calls. Implements additional logging\n and support for non-string keys.\n\n\n### Installation\n\n```shell\n$ pip install djcacheutils\n```\n\nand then (optional):\n\n```python\n# settings.py\nINSTALLED_APPS = (\n 'cache_utils',\n ...\n)\nCACHES = {\n 'default': {\n 'BACKEND': 'cache_utils.group_backend.CacheClass',\n 'LOCATION': '127.0.0.1:11211',\n },\n}\n```\n\n### Usage\n\n`cached` decorator can be used with any django caching backend (built-in or third-party like django-newcache)::\n\n```python\nfrom cache_utils.decorators import cached\n\n@cached(60)\ndef foo(x, y=0):\n print 'foo is called'\n return x+y\n\nfoo(1, 2) # foo is called\nfoo(1, 2)\n\nfoo(5, 6) # foo is called\nfoo(5, 6)\n\n# Invalidation\nfoo.invalidate(1, 2)\nfoo(1, 2) # foo is called\n\n# Force calculation\nfoo(5, 6)\nfoo.force_recalc(5, 6) # foo is called\n\nfoo(x=2) # foo is called\nfoo(x=2)\n\n# Require cache\nfoo.require_cache(7, 8) # NoCachedValueException is thrown\n```\n\nThe `@cached` decorator is also supported on class methods\n\n```python\nclass Foo(object):\n @cached(60)\n def foo(self, x, y):\n print \"foo is called\"\n return x + y\n\nobj = Foo()\nobj.foo(1, 2) # foo is called\nobj.foo(1, 2)\n```\n\nWith ``group_backend`` `cached` decorator supports bulk O(1) invalidation::\n\n```python\nfrom django.db import models\nfrom cache_utils.decorators import cached\n\nclass CityManager(models.Manager):\n\n # cache a method result. 'self' parameter is ignored\n @cached(60*60*24, 'cities')\n def default(self):\n return self.active()[0]\n\n # cache a method result. 'self' parameter is ignored, args and\n # kwargs are used to construct cache key\n @cached(60*60*24, 'cities')\n def get(self, *args, **kwargs):\n return super(CityManager, self).get(*args, **kwargs)\n\n\nclass City(models.Model):\n # ... field declarations\n\n objects = CityManager()\n\n # an example how to cache django model methods by instance id\n def has_offers(self):\n @cached(30)\n def offer_count(pk):\n return self.offer_set.count()\n return offer_count(self.pk) > 0\n\n# cache the function result based on passed parameter\n@cached(60*60*24, 'cities')\ndef get_cities(slug)\n return City.objects.get(slug=slug)\n\n\n# cache for 'cities' group can be invalidated at once\ndef invalidate_city(sender, **kwargs):\n cache.invalidate_group('cities')\npre_delete.connect(invalidate_city, City)\npost_save.connect(invalidate_city, City)\n```\n\nYou can force cache to be recalculated:\n\n```python\n@cached\ndef calc_function(x, y):\n return x*y\n\nx = calc_function.force_recalc(x, y)\n```\n\n### Cache Keys\n\n\nBy default, django-cache-utils constructs a key based on the function name, line number, args, and kwargs. Example:\n\n```python\n@cached(60)\ndef foo(a1):\n ...\n\nprint foo.get_cache_key('test') # ==> '[cached]package.module:15(('test',))'\n```\n\nNote given the line-number is included in the cache key, simple tweaks to a module not releveant to the @cached function will create a new cache key (and thus upon release old cached items will not get hit).\n\nIn these instances, it's recommended to provide an explicit `key` kwarg argument to the `@cached` decorator.\n\n```python\n@cached(60, key='foo')\ndef foo(a1):\n ...\n\nprint foo.get_cache_key('test') # ==> '[cached]foo(('test',))'\n```\n\n### Notes\n\nIf decorated function returns None cache will be bypassed.\n\ndjango-cache-utils use 2 reads from memcached to get a value if 'group'\nargument is passed to 'cached' decorator::\n\n```python\n@cached(60)\ndef foo(param)\n return ..\n\n@cached(60, 'my_group')\ndef bar(param)\n return ..\n\n# 1 read from memcached\nvalue1 = foo(1)\n\n# 2 reads from memcached + ability to invalidate all values at once\nvalue2 = bar(1)\n```\n\n### Logging\n\nTurn on `cache_utils` logger to DEBUG to log all cache set, hit, deletes.\n\n### Running tests\n\n```shell\n$ python setup.py test\n```", "description_content_type": null, "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/infoscout/django-cache-utils", "keywords": "", "license": "MIT license", "maintainer": "", "maintainer_email": "", "name": "djcacheutils", "package_url": "https://pypi.org/project/djcacheutils/", "platform": "", "project_url": "https://pypi.org/project/djcacheutils/", "project_urls": { "Homepage": "https://github.com/infoscout/django-cache-utils" }, "release_url": "https://pypi.org/project/djcacheutils/3.0.0/", "requires_dist": null, "requires_python": "", "summary": "Caching decorator and django cache backend with advanced invalidation ability and dog-pile effect prevention", "version": "3.0.0" }, "last_serial": 3007158, "releases": { "3.0.0": [ { "comment_text": "", "digests": { "md5": "d881405fcb492807a0615134a9e0e800", "sha256": "9f1058aa278ef507a2c06c14e152307c51f0046f4a136c81cf366a0700083e0f" }, "downloads": -1, "filename": "djcacheutils-3.0.0.tar.gz", "has_sig": false, "md5_digest": "d881405fcb492807a0615134a9e0e800", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9370, "upload_time": "2017-07-07T20:01:29", "url": "https://files.pythonhosted.org/packages/e1/31/7d49550cddfaadcecb60c6ff3ff9d341d86e114144b6e6d4754b95499554/djcacheutils-3.0.0.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "d881405fcb492807a0615134a9e0e800", "sha256": "9f1058aa278ef507a2c06c14e152307c51f0046f4a136c81cf366a0700083e0f" }, "downloads": -1, "filename": "djcacheutils-3.0.0.tar.gz", "has_sig": false, "md5_digest": "d881405fcb492807a0615134a9e0e800", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9370, "upload_time": "2017-07-07T20:01:29", "url": "https://files.pythonhosted.org/packages/e1/31/7d49550cddfaadcecb60c6ff3ff9d341d86e114144b6e6d4754b95499554/djcacheutils-3.0.0.tar.gz" } ] }