{"id":6304,"library":"adrf","title":"Async Django REST Framework","description":"ADRF (Async Django REST Framework) is a Python library that provides asynchronous support for Django REST framework. It allows developers to write async class and function-based views, viewsets, and serializers, leveraging Django's native async capabilities (Django 4.1+). The library is currently at version 0.1.12 and maintains an active release cadence with regular updates and bug fixes.","status":"active","version":"0.1.12","language":"en","source_language":"en","source_url":"https://github.com/em1208/adrf","tags":["async","django","drf","rest-framework","api","asynchronous"],"install":[{"cmd":"pip install adrf","lang":"bash","label":"Install `adrf`"},{"cmd":"# In your Django project's settings.py\nINSTALLED_APPS = [\n    # ...\n    'rest_framework',\n    'adrf',\n    # ...\n]","lang":"python","label":"Add to INSTALLED_APPS"}],"dependencies":[{"reason":"Requires Django 4.1+ for async features.","package":"django","optional":false},{"reason":"Extends DRF functionality for async operations.","package":"djangorestframework","optional":false}],"imports":[{"symbol":"APIView","correct":"from adrf.views import APIView"},{"symbol":"api_view","correct":"from adrf.decorators import api_view"},{"symbol":"ListCreateAPIView","correct":"from adrf.generics import ListCreateAPIView"},{"symbol":"ModelViewSet","correct":"from adrf.viewsets import ModelViewSet"},{"note":"Use adrf's router for async ModelViewSet methods to be recognized.","wrong":"from rest_framework.routers import DefaultRouter","symbol":"Router","correct":"from adrf.routers import DefaultRouter"}],"quickstart":{"code":"import os\nimport django\nfrom django.conf import settings\nfrom django.urls import path\nfrom rest_framework.response import Response\nfrom adrf.views import APIView\nfrom adrf.decorators import api_view\nfrom adrf.generics import ListCreateAPIView\nfrom adrf.viewsets import ModelViewSet\nfrom adrf.routers import DefaultRouter\nfrom rest_framework import serializers\n\n# Minimal Django settings for a runnable example\nsettings.configure(\n    DEBUG=True,\n    SECRET_KEY=os.environ.get('DJANGO_SECRET_KEY', 'a-very-secret-key'),\n    INSTALLED_APPS=[\n        'django.contrib.auth',\n        'django.contrib.contenttypes',\n        'rest_framework',\n        'adrf',\n        'adrf_app' # A dummy app for models/serializers\n    ],\n    DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': ':memory:'}},\n    ROOT_URLCONF=__name__,\n    TEMPLATES=[{\n        'BACKEND': 'django.template.backends.django.DjangoTemplates',\n        'APP_DIRS': True,\n    }],\n    ASGI_APPLICATION='adrf_app.asgi.application' # Important for async\n)\n\n# Create a dummy app for models/serializers\n# In a real project, this would be a separate app directory\nclass AdrfAppConfig(django.apps.AppConfig):\n    name = 'adrf_app'\n    label = 'adrf_app'\n    verbose_name = 'ADRF App'\n\nsettings.INSTALLED_APPS.append(AdrfAppConfig.name)\n\ndjango.setup()\n\n# Dummy Model\nfrom django.db import models\n\nclass Item(models.Model):\n    name = models.CharField(max_length=100)\n    value = models.IntegerField()\n\n    def __str__(self):\n        return self.name\n\n# Dummy Serializer\nclass ItemSerializer(serializers.ModelSerializer):\n    class Meta:\n        model = Item\n        fields = '__all__'\n\n# Async Class-Based View\nclass AsyncItemView(APIView):\n    async def get(self, request, *args, **kwargs):\n        await Item.objects.acreate(name=\"Fetched Item\", value=100) # Example async ORM\n        return Response({\"message\": \"This is an async class-based view!\"})\n\n# Async Function-Based View\n@api_view(['GET'])\nasync def async_function_view(request):\n    await Item.objects.acreate(name=\"Function Item\", value=200)\n    return Response({\"message\": \"This is an async function-based view!\"})\n\n# Async Generic View\nclass AsyncItemListView(ListCreateAPIView):\n    queryset = Item.objects.all()\n    serializer_class = ItemSerializer\n\n    async def get_queryset(self): # Override to ensure async ORM\n        return await super().get_queryset().filter(value__gt=50)\n\n    async def aperform_create(self, serializer):\n        await serializer.asave() # Use async save\n\n# Async ModelViewSet\nclass AsyncItemViewSet(ModelViewSet):\n    queryset = Item.objects.all()\n    serializer_class = ItemSerializer\n\n    # adrf's ModelViewSet automatically wraps common ORM operations in sync_to_async\n    # but you can override specific async methods like 'alist' or 'aretrieve'\n    async def alist(self, request, *args, **kwargs):\n        await Item.objects.acreate(name=\"ViewSet List Item\", value=300)\n        return await super().alist(request, *args, **kwargs)\n\n# Setup URLs\nrouter = DefaultRouter()\nrouter.register(r'items-viewset', AsyncItemViewSet)\n\nurlpatterns = [\n    path('async-class-view/', AsyncItemView.as_view()),\n    path('async-function-view/', async_function_view),\n    path('async-generic-list/', AsyncItemListView.as_view()),\n] + router.urls\n\n# To run this example (requires ASGI server like uvicorn):\n# 1. Save this code as e.g., `my_adrf_app.py`\n# 2. Run from your terminal: `uvicorn my_adrf_app:urlpatterns --reload` (or specify an ASGI app entry point if using a real project structure)\n# 3. Access in browser: http://127.0.0.1:8000/async-class-view/","lang":"python","description":"This quickstart demonstrates setting up `adrf` with async class-based views, function-based views, generic views, and a ModelViewSet. It includes a basic Django setup, a dummy model, and a serializer. Note the use of `async def` for view methods and `adrf`'s specific router for ModelViewSets. To run, save as a Python file and serve with an ASGI server like Uvicorn (e.g., `uvicorn your_file_name:urlpatterns --reload`)."},"warnings":[{"fix":"Ensure all HTTP method handlers (e.g., `get`, `post`, `put`) in `APIView` subclasses and all action methods (e.g., `list`, `create`, `retrieve`, `update`, `destroy`) in `ViewSet`/`ModelViewSet` subclasses are defined with `async def`.","message":"All handler methods in `adrf` class-based views and viewsets must be asynchronous (e.g., `async def get(self, request):`). Synchronous handlers will raise exceptions in an async context.","severity":"breaking","affected_versions":"All versions"},{"fix":"Replace `from rest_framework.routers import DefaultRouter` with `from adrf.routers import DefaultRouter` in your `urls.py`.","message":"When using `ModelViewSet` with `adrf`, you must use `adrf.routers.DefaultRouter` instead of `rest_framework.routers.DefaultRouter`. The default DRF router will not correctly map to `adrf`'s async CRUD actions (e.g., `aretrieve`, `alist`).","severity":"gotcha","affected_versions":"All versions"},{"fix":"For any synchronous code that interacts with the Django ORM or other blocking operations within an `async def` function, wrap it using `from asgiref.sync import sync_to_async` (e.g., `await sync_to_async(blocking_function)()`). `adrf` versions 0.1.10 and 0.1.11 included fixes for pagination and general ORM operations, but vigilance is still required for custom logic.","message":"Calling synchronous Django ORM operations directly from an async context can lead to `SynchronousOnlyOperation` errors. While `adrf` wraps many common ORM operations, custom or complex synchronous database calls still require explicit handling.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure your Django project is running Django 4.1 or a newer version. It is also recommended to use the latest patch release of your chosen Django series.","message":"`adrf` officially supports Django 4.1 and above. Using it with older Django versions may lead to unexpected behavior or missing async features, as Django's native async support was introduced and matured in these versions.","severity":"gotcha","affected_versions":"< 4.1"}],"env_vars":null,"last_verified":"2026-04-15T00:00:00.000Z","next_check":"2026-07-14T00:00:00.000Z"}