Skip to main content

Async caching with MD5 and OpenAPI schema generation for ADRF (Asynchronous Django Rest Framework) and Django 5.0+

Project description

adrf-caching

A high-performance library that extends ADRF (Asynchronous Django REST Framework) with intelligent, per-user async caching. It reduces database load and decreases response times by leveraging asynchronous cache operations and a smart invalidation strategy based on user-specific versioning.

🚀 Key Features

Contains asynchronous caching mixins, generics and viewsets for Async Django Rest Framework and Django 5.0+:

  • 100% Asynchronous: Built from the ground up with async/await, ensuring non-blocking I/O for database and cache operations.
  • Automatic Async Caching: Seamlessly caches results to your configured cache backend (e.g., Redis) using Django Async Caching.
  • Smart Invalidation (Cache Versioning): Instead of manually clearing complex cache keys, it uses a versioning system. When a user modifies data, their specific version increments, instantly invalidating outdated lists.
  • Secure Data Isolation: Prevents data leakage by incorporating unique user hashes and versions into cache keys.
  • MD5 Hashing: Optimized performance using md5 for compact and consistent cache keys.
  • OpenAPI Support: Fully compatible with drf-spectacular scheme generator. It includes built-in method bridging to ensure async actions are correctly indexed by the schema inspector.

🛠 Prerequisites

⚙️ Installation

pip install adrf-caching

📖 Usage Guide

This library provides three levels of integration: Generics (pre-built views), ViewSets (ready-to-use CRUD classes), and Mixins (for custom logic).

1. Using Cached ViewSets (Recommended for CRUD)

The easiest way to implement full CRUD with caching is to inherit from the cached ViewSet classes. These classes bridge ADRF's async capabilities with the caching logic.

from adrf_caching.viewsets import ModelViewSetCached, ReadOnlyModelViewSetCached
from .models import Post
from .serializers import PostSerializer

# Full CRUD (Create, List, Retrieve, Update, Delete) with Cache
class PostViewSet(ModelViewSetCached):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

# Read-only API (List, Retrieve) with Cache
class PostReadOnlyViewSet(ReadOnlyModelViewSetCached):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

2. Using Concrete Generics (Fastest)

The simplest way is to inherit from pre-built generic views in generics.py. These already include both ADRF's async logic and the caching mixins.

from adrf_caching.generics import ListCreateAPIView
from .models import Book
from .serializers import BookSerializer

class BookListCreateView(ListCreateAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

3. Adding Mixins to Existing ADRF Classes (Flexible)

If you already have a class based on adrf.generics.GenericAPIView, you can inject the caching logic by placing the mixins before any other classes in the inheritance chain.

from adrf.viewsets import GenericViewSet
from adrf_caching.mixins import ListModelMixin, RetrieveModelMixin
from .models import Profile
from .serializers import ProfileSerializer

class ProfileViewSet(ListModelMixin, RetrieveModelMixin, GenericViewSet):
    queryset = Profile.objects.all()
    serializer_class = ProfileSerializer

📜 OpenAPI Schema & Documentation

The library is optimized for drf-spectacular.

Since drf-spectacular and many other libs expects standard DRF action names, we use a preprocessing hook to map async methods (like alist, aretrieve) back to their standard counterparts during schema generation. This ensures that features like pagination, filters, and correct response types are automatically detected.

SPECTACULAR_SETTINGS = {
    'PREPROCESSING_HOOKS': [
        'adrf_caching.utils.preprocess_async_actions',
    ]
}

When using ViewSets, explicit method mapping in urls.py recommended. This helps the schema inspector distinguish between different actions (like list and retrieve) and prevents collisions.

from django.urls import path
from . import views

urlpatterns = [
    # Explicit mapping for ViewSets ensures clean OpenAPI IDs
    path("items/", views.ItemViewSet.as_view({'get': 'alist', 'post': 'acreate'})),
    path("items/<int:pk>/", views.ItemViewSet.as_view({'get': 'aretrieve', 'put': 'aupdate'})),
]

Even though the library uses async methods internally (e.g., alist, acreate), you should use standard DRF action names as keys in your schema decorators. The base classes bridge these names automatically to provide a seamless documentation experience.

from drf_spectacular.utils import extend_schema, extend_schema_view

@extend_schema_view(
    list=extend_schema(summary="List all items"),
    retrieve=extend_schema(summary="Get item details"),
)
class ItemViewSet(ModelViewSetCached):
    queryset = Item.objects.all()
    serializer_class = ItemSerializer

Extra

To ensure correct object caching after creation or updates, the library looks for the id field by default. If your model uses a different primary key (e.g., uuid or slug or one to one relation), you must specify it in the serializer using the 'custom_id' attribute:

class MySerializer(serializers.ModelSerializer):
    custom_id = "uuid"  # Set this if your primary key is not 'id'
    
    class Meta:
        model = MyModel
        fields = "__all__"

🏃 Running Tests

The library uses Django's TransactionTestCase to ensure database integrity during async operations.

# Run all tests
python -m unittest discover tests -p "*_test.py"

# Run a specific test file
python -m unittest tests/viewsets_test.py

# Run a specific test class
python -m unittest tests.viewsets_test.TestCacheSystem

You can use the standard Django test runner:

# Run all tests
python manage.py test tests.utils_test tests.viewsets_test tests.generics_test

# Run a specific test class
python manage.py test tests.viewsets_test.TestCacheSystem

License

Apache 2.0 License

django async, drf async, adrf, django 5 async views, async serializers, async caching, drf caching, asynchronous drf, adrf, django rest framework, python async api, drf-spectacular, OpenAPI 3.0, Swagger, Redoc, async api documentation, schema generation, adrf-spectacular

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

adrf_caching-0.1.2.tar.gz (12.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

adrf_caching-0.1.2-py3-none-any.whl (11.5 kB view details)

Uploaded Python 3

File details

Details for the file adrf_caching-0.1.2.tar.gz.

File metadata

  • Download URL: adrf_caching-0.1.2.tar.gz
  • Upload date:
  • Size: 12.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for adrf_caching-0.1.2.tar.gz
Algorithm Hash digest
SHA256 fabfb9e3a5f7fb3b8ce240285869f52f679c48b2a5b95f9f1113bc8c7f22f505
MD5 68b7491202b9def73f68344eb040ec9f
BLAKE2b-256 0a01de689f0a94da50ba36b957f9d103aaa9f698c18fd7337f55e74d2d763dbf

See more details on using hashes here.

File details

Details for the file adrf_caching-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: adrf_caching-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 11.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for adrf_caching-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 41ee8b0c2bac6d2bf6dce681ae526778277f623ea7d647e095e24ea317cedb02
MD5 e7808a89975e33b8ecc9c909be94069d
BLAKE2b-256 ecacfd6037b5f50147479675088a7a17d72043cf9bb70ee58c2e4e83ab23cdd7

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page