Registry / database / django-cacheops

django-cacheops

JSON →
library7.2pypypiunverified

django-cacheops is a slick ORM cache for Django, offering automatic granular event-driven invalidation. It leverages Redis for high-performance caching. Currently at version 7.2, it maintains an active development cycle with regular updates supporting recent Django and Python versions.

pip install django-cacheops
INSTALL
IMPORT
SIG · DJANGO-CACHEOPS
D
django-cacheops
databasepythonv7.2
Install
3.8s avg
Import
Disk
71MB
Pass rate
10/ 10
Env Coverage10 / 10
glibc
3.93.13
musl
3.93.13
Install & Compatibility
Where this runs
tested against v7.2 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
musl
py 3.103.920 runs
installs and imports cleanly · install 0.0s · import 0.000s · 71.6MB
glibc
py 3.103.920 runs
installs and imports cleanly · install 3.8s · import 0.000s · 72MB
71MB installed
● package 71MB
Code
Verified usage

Verified import paths — ran on the pinned version, not inferred.

cached
from cacheops import cached
from cacheops import cached_queryset
invalidate_obj
from cacheops import invalidate_obj
invalidate_model
from cacheops import invalidate_model

This quickstart demonstrates how to configure django-cacheops with minimal Django settings and use its core features: caching querysets with `.cache()`, explicit model invalidation, and the `@cached_queryset` decorator for functions returning querysets. It assumes a Redis server is accessible at `redis://localhost:6379/1` or specified via the `CACHEOPS_REDIS` environment variable.

import os import django from django.conf import settings from django.db import models # Minimal Django settings for a runnable example # In a real project, these would be in your settings.py if not settings.configured: settings.configure( INSTALLED_APPS=[ 'django.contrib.auth', 'django.contrib.contenttypes', 'cacheops', # Add cacheops to your installed apps 'myapp', # A dummy app for model definition ], CACHEOPS_REDIS=os.environ.get('CACHEOPS_REDIS', 'redis://localhost:6379/1'), # CACHEOPS_ENABLED defaults to True since v7.0 # CACHEOPS_TIMEOUT defaults to 3600 (1 hour) since v7.0 DATABASES={ 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:', } }, USE_TZ=True, TIME_ZONE='UTC', ) django.setup() # Define a simple Django model. For demonstration, we use 'myapp' as app_label. class Post(models.Model): title = models.CharField(max_length=200) body = models.TextField() created_at = models.DateTimeField(auto_now_add=True) class Meta: app_label = 'myapp' # Required when defining models outside an actual app directory def __str__(self): return self.title # Ensure the database schema is created for the model (for in-memory SQLite) from django.db import connection with connection.schema_editor() as schema_editor: schema_editor.create_model(Post) print(f"Using Redis connection string: {settings.CACHEOPS_REDIS}") # Create some sample data Post.objects.create(title="First Post", body="Content of the first post.") Post.objects.create(title="Second Article", body="More content here.") # --- Example 1: Caching a Queryset --- print("\n--- Example 1: Caching a Queryset ---") # The .cache() method makes the queryset result be cached. # First call will hit the database and store the result in cache. posts = Post.objects.filter(title__icontains='post').cache().all() print(f"Posts (first fetch, hits DB and caches): {[p.title for p in posts]}") # Subsequent calls with the same query parameters will hit the cache. posts_cached = Post.objects.filter(title__icontains='post').cache().all() print(f"Posts (second fetch, should hit cache): {[p.title for p in posts_cached]}") # --- Example 2: Invalidating Cache --- from cacheops import invalidate_model print("\n--- Example 2: Invalidating Cache ---") # Update an object (usually auto-invalidates if configured) post_to_update = Post.objects.get(title="First Post") post_to_update.title = "Updated First Post" post_to_update.save() # Explicitly invalidate all caches related to the Post model invalidate_model(Post) print("Post model cache explicitly invalidated.") # Fetching again will hit the DB to get the updated data and re-cache. updated_posts = Post.objects.filter(title__icontains='post').cache().all() print(f"Posts after update and invalidation: {[p.title for p in updated_posts]}") # --- Example 3: Using @cached_queryset decorator --- from cacheops import cached_queryset print("\n--- Example 3: Using @cached_queryset decorator ---") @cached_queryset def get_latest_articles(limit=1): print(" (Fetching from DB inside get_latest_articles)") return Post.objects.order_by('-created_at')[:limit] # First call of the decorated function latest1 = get_latest_articles() print(f"Latest article (first call): {[p.title for p in latest1]}") # Second call of the decorated function should hit the cache latest2 = get_latest_articles() print(f"Latest article (second call, should hit cache): {[p.title for p in latest2]}")
Debug
Known issues
breakingIn version 7.0, `CACHEOPS_ENABLED` default changed from `False` to `True`, and `CACHEOPS_TIMEOUT` changed from `None` (never expire) to `3600` seconds (1 hour). This can lead to unexpected caching behavior or premature cache expiration if your project relied on the previous defaults without explicit configuration.
fix
Explicitly set `CACHEOPS_ENABLED = False` or define your desired `CACHEOPS_TIMEOUT` in Django settings to maintain previous behavior or fine-tune cache lifespan.
affects: >=7.0
breakingAs of version 7.0, django-cacheops requires Python 3.7+ and Django 3.2+.
fix
Upgrade your Python environment to 3.7 or newer and your Django project to 3.2 or newer. For older Django/Python versions, use django-cacheops < 7.0 (e.g., version 6.x).
affects: >=7.0
gotchaCaching within database transactions can lead to stale reads if the transaction is rolled back or if other processes read cached data before the transaction commits. Cacheops might cache pre-commit data.
fix
For operations that create/update objects within a transaction, use `transaction.on_commit` to invalidate or perform cache updates only after the transaction successfully commits. Alternatively, use `cacheops.transaction.atomic` for specific transactional cache handling.
affects: All
gotchaIncorrect Redis configuration (`CACHEOPS_REDIS`) or an inaccessible Redis server will cause `ConnectionError`s or make Cacheops silently fail (act as a no-op, passing queries through to the DB).
fix
Ensure Redis is running and accessible from your application. Verify the `CACHEOPS_REDIS` setting in your `settings.py` (e.g., `redis://localhost:6379/1`). Check Redis logs and network connectivity.
affects: All
Upgrade
Version history
7.2latest on PyPI · released Apr 20, 2025
Audit
Dependencies
redisrequiredRedis server and client library are required for cache backend operations. Ensure a Redis server is running and accessible.
Agent activity
6 hits · last 30 days
node
6
Resources
django-cacheops — pip install django-cacheops · libregistry