Expose Django REST-like API over a WebSocket connection
Django Channels REST framework is a selection of useful tools for building WebSocket API consumers with Django Channels v2. It focuses on enabling you to reuse your existing Django REST framework code.
One of the key features that DCRF provides is the ability to easily create JSON WebSocket consumers that can expose REST-like actions in the same way as the GenericApiView in DRF.
from django.contrib.auth import get_user_model
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import ListModelMixin
from . import serializers
class UserConsumer(ListModelMixin, GenericAsyncAPIConsumer):
queryset = get_user_modle().objects.all()
serializer_class = serializers.UserSerializer
permission_classes = (permissions.IsAuthenticated,)
This consumer will expose a list
action that you can call over the WebSocket connection by sending a ws
message.
{
"action": "list",
"request_id": 42 // this value is included in your response message, to help you track multiple pending actions
}
The consumer will use your queryset
to retrieve a list of items and encode a JSON response using the DRF serializer_class
provided. Like GeneicApiViews
in DRF you can override get_queryset
and filter_queryset
methods.
DCRF includes a collection of other usefull ModelMixins
:
- CreateModelMixin
- ListModelMixin
- RetrieveModelMixin
- UpdateModelMixin
- PatchModelMixin
- DeleteModelMixin
These can be added to the GenericAsyncAPIConsumer
as mixins.
To use them over the WebSocket you will need to include the action value action: "update"
. For actions that operate on a model instance (retrieve, update, patch and delete) you also need pk: 42
. Then include the data for your action: data: {"username": "bob"}
.
# Adding custom actions
In a normal REST API sometimes we need to add custom action endpoints that are outside of the regular CRUD operations we all know and love. With DCRF there is a convenient @action()
method decorator that you can add to a method to expose it to your WebSocket clients.
from djangochannelsrestframework.decorators import action
from djangochannelsrestframework.consumers import AsyncAPIConsumer
class MyConsumer(AsyncAPIConsumer):
@action()
async def an_async_action(self, some=None, **kwargs):
# do something async
return {'response_with': 'some message'}, 200
In your client you would send a message like this.
{
"action": "an_async_action",
"request_id": 42,
"some": "value passed as keyword argument to action"
}
You can also add actions to your GenericAsyncAPIConsumer
, so that you can have multiple methods on the same consumer (this is how the mixins
add their actions).
# Calling your Django views over WebSocket
It is also possible to use view_as_consumer
method to automatically wrap an existing Django view to be accessible over a WebSocket connection.
from djangochannelsrestframework.consumers import view_as_consumer
application = ProtocolTypeRouter({
"websocket": AuthMiddlewareStack(
URLRouter([
url(r"^front(end)/$", view_as_consumer(YourDjangoView)),
])
),
})
When using DCRF it is very helpful to set up multiple consumers behind a multiplexing layer, so that you can have a single WebSocket connection call multiple consumers concurrently.