### PatchModelMixin Consumer Example
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/mixins.html
Example of a consumer using PatchModelMixin for partial updates. Requires setup in consumers.py.
```python
#! consumers.py
from .models import User
from .serializers import UserSerializer
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import PatchModelMixin
class LiveConsumer(PatchModelMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny,)
```
--------------------------------
### PatchModelMixin Consumer Setup
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/mixins.html
Example of setting up a consumer with PatchModelMixin for patching model instances. Requires defining queryset, serializer_class, and permission_classes.
```python
from .models import User
from .serializers import UserSerializer
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import PatchModelMixin
class LiveConsumer(PatchModelMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny,)
```
--------------------------------
### PatchModelMixin Routing Example
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/mixins.html
Example of how to route WebSocket connections to a consumer that uses PatchModelMixin. Requires setup in routing.py.
```python
#! routing.py
from django.urls import re_path
from .consumers import LiveConsumer
websocket_urlpatterns = [
re_path(r'^ws/$', LiveConsumer.as_asgi()),
]
```
--------------------------------
### Create Model Consumer Example
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/mixins.html
Example of a consumer using CreateModelMixin to handle model creation requests. Requires setup in routing.py and a WebSocket client to send 'create' actions.
```Python
#! consumers.py
from .models import User
from .serializers import UserSerializer
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import CreateModelMixin
class LiveConsumer(CreateModelMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny,)
```
```Python
#! routing.py
from django.urls import re_path
from .consumers import LiveConsumer
websocket_urlpatterns = [
re_path(r'^ws/$', LiveConsumer.as_asgi()),
]
```
```JavaScript
// html
const ws = new WebSocket("ws://localhost:8000/ws/")
ws.send(JSON.stringify({
action: "create",
request_id: new Date().getTime(),
data: {
username: "test",
password1: "testpassword123",
password2: "testpassword123",
}
}))
/* The response will be something like this.
{
"action": "create",
"errors": [],
"response_status": 201,
"request_id": 150060530,
"data": {'username': 'test', 'id': 42,},
}
*/
```
--------------------------------
### CreateModelMixin: Create Action Example
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/mixins.html
Demonstrates how to use CreateModelMixin to create a new model instance. Includes consumer, routing, and client-side JavaScript examples.
```python
from .models import User
from .serializers import UserSerializer
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import CreateModelMixin
class LiveConsumer(CreateModelMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny,)
```
```python
from django.urls import re_path
from .consumers import LiveConsumer
websocket_urlpatterns = [
re_path(r'^ws/$', LiveConsumer.as_asgi()),
]
```
```javascript
// html
const ws = new WebSocket("ws://localhost:8000/ws/")
ws.send(JSON.stringify({
action: "create",
request_id: new Date().getTime(),
data: {
username: "test",
password1: "testpassword123",
password2: "testpassword123",
}
}))
/* The response will be something like this.
{
"action": "create",
"errors": [],
"response_status": 201,
"request_id": 150060530,
"data": {'username': 'test', 'id': 42,},
}
*/
```
--------------------------------
### UpdateModelMixin Consumer Setup
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/mixins.html
Example of setting up a consumer with UpdateModelMixin for updating model instances. Requires defining queryset, serializer_class, and permission_classes.
```python
from .models import User
from .serializers import UserSerializer
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import UpdateModelMixin
class LiveConsumer(UpdateModelMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny,)
```
--------------------------------
### ListModelMixin: List Action Example
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/mixins.html
Illustrates how to use ListModelMixin to retrieve a list of model instances. Includes consumer, routing, and client-side JavaScript examples.
```python
from .models import User
from .serializers import UserSerializer
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import ListModelMixin
class LiveConsumer(ListModelMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny,)
```
```python
from django.urls import re_path
from .consumers import LiveConsumer
websocket_urlpatterns = [
re_path(r'^ws/$', LiveConsumer.as_asgi()),
]
```
```javascript
// html
const ws = new WebSocket("ws://localhost:8000/ws/")
ws.send(JSON.stringify({
action: "list",
request_id: new Date().getTime(),
}))
/* The response will be something like this.
{
"action": "list",
"errors": [],
"response_status": 200,
"request_id": 1500000,
"data": [
{"email": "42@example.com", "id": 1, "username": "test1"},
{"email": "45@example.com", "id": 2, "username": "test2"},
],
}
*/
```
--------------------------------
### RetrieveModelMixin Consumer Setup
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/mixins.html
Example of setting up a consumer with RetrieveModelMixin for retrieving a specific model instance. Requires defining queryset, serializer_class, and permission_classes.
```python
from .models import User
from .serializers import UserSerializer
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import RetrieveModelMixin
class LiveConsumer(RetrieveModelMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny,)
```
--------------------------------
### List Model Consumer Example
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/mixins.html
Example of a consumer using ListModelMixin to handle model listing requests. Requires setup in routing.py and a WebSocket client to send 'list' actions.
```Python
#! consumers.py
from .models import User
from .serializers import UserSerializer
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import ListModelMixin
class LiveConsumer(ListModelMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny,)
```
```Python
#! routing.py
from django.urls import re_path
from .consumers import LiveConsumer
websocket_urlpatterns = [
re_path(r'^ws/$', LiveConsumer.as_asgi()),
]
```
```JavaScript
// html
const ws = new WebSocket("ws://localhost:8000/ws/")
ws.send(JSON.stringify({
action: "list",
request_id: new Date().getTime(),
}))
/* The response will be something like this.
{
"action": "list",
"errors": [],
"response_status": 200,
"request_id": 1500000,
"data": [
{"email": "42@example.com", "id": 1, "username": "test1"},
{"email": "45@example.com", "id": 2, "username": "test2"},
],
}
*/
```
--------------------------------
### RetrieveModelMixin Consumer Example
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/mixins.html
Example of a consumer using RetrieveModelMixin to fetch a single model instance. Requires setup in consumers.py and routing.py, and client-side WebSocket connection.
```python
#! consumers.py
from .models import User
from .serializers import UserSerializer
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import RetrieveModelMixin
class LiveConsumer(RetrieveModelMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny,)
```
```python
#! routing.py
from django.urls import re_path
from .consumers import LiveConsumer
websocket_urlpatterns = [
re_path(r'^ws/$', LiveConsumer.as_asgi()),
]
```
```javascript
// html
const ws = new WebSocket("ws://localhost:8000/ws/")
ws.send(JSON.stringify({
action: "retrieve",
request_id: new Date().getTime(),
pk: 1,
}))
/* The response will be something like this.
{
"action": "retrieve",
"errors": [],
"response_status": 200,
"request_id": 1500000,
"data": {"email": "42@example.com", "id": 1, "username": "test1"},
}
*/
```
--------------------------------
### DeleteModelMixin Consumer Example
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/mixins.html
Example of a consumer using DeleteModelMixin for deleting model instances. Requires setup in consumers.py.
```python
#! consumers.py
from .models import User
from .serializers import UserSerializer
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import DeleteModelMixin
class LiveConsumer(DeleteModelMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny,)
```
--------------------------------
### Delete Model Consumer Example
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/mixins.html
Example of a consumer using DeleteModelMixin to handle model deletion requests. Requires setup in routing.py and a WebSocket client to send 'delete' actions with a primary key.
```Python
#! consumers.py
from .models import User
from .serializers import UserSerializer
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import DeleteModelMixin
class LiveConsumer(DeleteModelMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny,)
```
```Python
#! routing.py
from django.urls import re_path
from .consumers import LiveConsumer
websocket_urlpatterns = [
re_path(r'^ws/$', LiveConsumer.as_asgi()),
]
```
```JavaScript
// html
const ws = new WebSocket("ws://localhost:8000/ws/")
ws.send(JSON.stringify({
action: "delete",
request_id: new Date().getTime(),
pk: 1,
}))
/* The response will be something like this.
{
"action": "delete",
"errors": [],
"response_status": 204,
"request_id": 150000,
"data": null,
}
*/
```
--------------------------------
### Example Remote Action Call
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/decorators.html
This JavaScript example demonstrates how a client can send a message to invoke a remote action on the consumer. The message structure includes the action name and any required arguments.
```javascript
{
action: "delete_user",
request_id: 42,
user_pk: 82
}
```
--------------------------------
### Install Django Channels REST Framework
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_sources/introduction.rst.txt
Command to install the djangochannelsrestframework package using pip. Ensure you also add 'channels' to your Django project's INSTALLED_APPS.
```bash
pip install djangochannelsrestframework
```
--------------------------------
### Basic Model Observer Setup
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/observer/observer.html
Sets up an observer for `Comment` model changes and sends updates to subscribed clients. Requires a custom serializer for the observer.
```python
from djangochannelsrestframework.consumers import GenericAsyncAPIConsumer
from djangochannelsrestframework.observer import model_observer
from djangochannelsrestframework.decorators import action
from .serializers import UserSerializer, CommentSerializer
from .models import User, Comment
class MyConsumer(GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
@model_observer(Comment)
async def comment_activity(self, message, observer=None, subscribing_request_ids=[], **kwargs):
for request_id in subscribing_request_ids:
await self.send_json({"message": message, "request_id": request_id})
@comment_activity.serializer
def comment_activity(self, instance: Comment, action, **kwargs):
return CommentSerializer(instance).data
@action()
async def subscribe_to_comment_activity(self, request_id, **kwargs):
await self.comment_activity.subscribe(request_id=request_id)
```
--------------------------------
### Example WebSocket Response for User List
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/examples/view_as_consumer.html
An example of the JSON response received from the WebSocket server when requesting a list of users. Includes data, errors, and request details.
```json
{
"error": [],
"data": [
{"username": "user 1", "id": 1, "email": "1@example.com"},
{"username": "user 2", "id": 2, "email": "2@example.com"},
],
"action": "list",
"response_status": 200,
"request_id": 15050500
}
```
--------------------------------
### Basic Observer Consumer Setup
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/observer/observer.html
Defines a consumer that uses ObserverModelInstanceMixin to observe model instances. It sets the queryset and serializer class for handling user-related data.
```python
from djangochannelsrestframework.consumers import GenericAsyncAPIConsumer
from djangochannelsrestframework.observer.generics import ObserverModelInstanceMixin
from .serializers import UserSerializer
from .models import User
class MyConsumer(ObserverModelInstanceMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
observer_many_to_many_relationships = True
```
--------------------------------
### UpdateModelMixin Consumer Example
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/mixins.html
Example of a consumer using UpdateModelMixin to modify a single model instance. Includes consumer, routing, and client-side JavaScript for sending update requests.
```python
#! consumers.py
from .models import User
from .serializers import UserSerializer
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import UpdateModelMixin
class LiveConsumer(UpdateModelMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (permissions.AllowAny,)
```
```python
#! routing.py
from django.urls import re_path
from .consumers import LiveConsumer
websocket_urlpatterns = [
re_path(r'^ws/$', LiveConsumer.as_asgi()),
]
```
```javascript
// html
const ws = new WebSocket("ws://localhost:8000/ws/")
ws.send(JSON.stringify({
action: "update",
request_id: new Date().getTime(),
pk: 1,
data: {
username: "test edited",
},
}))
/* The response will be something like this.
{
"action": "update",
"errors": [],
"response_status": 200,
"request_id": 1500000,
"data": {"email": "42@example.com", "id": 1, "username": "test edited"},
}
*/
```
--------------------------------
### Example WebSocket Response for User List
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_sources/examples/view_as_consumer.rst.txt
Illustrates the expected JSON response structure from the WebSocket when requesting a list of users.
```javascript
{
error: [],
data: [
{username: "user 1", id: 1, email: "1@example.com"},
{username: "user 2", id: 2, email: "2@example.com"},
],
action: "list",
response_status: 200,
request_id: 15050500
}
```
--------------------------------
### Basic WebSocket Subscription
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/examples/filtered_model_observer.html
Establishes a WebSocket connection and subscribes to comment activity. This example does not require user authentication for subscription.
```javascript
const ws = new WebSocket("ws://localhost:8000/ws/my-consumer/")
const ws.onopen = function(){
ws.send(JSON.stringify({
action: "subscribe_to_comment_activity",
request_id: new Date().getTime(),
}))
}
const ws.onmessage = function(e){
console.log(e)
}
```
--------------------------------
### ObserverModelInstanceMixin Example
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/observer/generics.html
Demonstrates how to use ObserverModelInstanceMixin with GenericAsyncAPIConsumer to track model instance changes. Set `observer_many_to_many_relationships` to True to include many-to-many relationship changes.
```python
from djangochannelsrestframework.consumers import GenericAsyncAPIConsumer
from djangochannelsrestframework.observer.generics import ObserverModelInstanceMixin
from .serializers import UserSerializer
from .models import User
class MyConsumer(ObserverModelInstanceMixin, GenericAsyncAPIConsumer):
queryset = User.objects.all()
serializer_class = UserSerializer
observer_many_to_many_relationships = True
```
--------------------------------
### HTML and JavaScript WebSocket Client
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/examples/generic_api_consumer.html
A frontend example demonstrating how to connect to a WebSocket, send various API actions (list, retrieve, create, patch, update, delete), and display the response. Ensure the WebSocket server is running at ws://localhost:8000/ws/.
```html
Generic Api Consumer
```
--------------------------------
### PatchModelMixin Client-Side Example
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/mixins.html
Client-side JavaScript code to send a patch request to a consumer using PatchModelMixin. Demonstrates sending data and expected response format.
```javascript
// html
const ws = new WebSocket("ws://localhost:8000/ws/")
ws.send(JSON.stringify({
action: "patch",
request_id: new Date().getTime(),
pk: 1,
data: {
email: "00@example.com",
},
}))
/* The response will be something like this.
{
"action": "patch",
"errors": [],
"response_status": 200,
"request_id": 150000,
"data": {"email": "00@example.com", "id": 1, "username": "test1"},
}
*/
```
--------------------------------
### Combine Permission Classes with Boolean Operations
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_sources/permissions.rst.txt
This example demonstrates combining multiple permission classes, such as `MyCustomPermission` and `IsAuthenticated`, using boolean operators like the OR operator (`|`).
```python
from djangochannelsrestframework.consumers import AsyncAPIConsumer
from djangochannelsrestframework.permissions import IsAuthenticated
class RoomConsumer(AsyncAPIConsumer):
permission_classes = [
MyCustomPermission | IsAuthenticated
]
```
--------------------------------
### Observer Groups for Consumer Subscription
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/observer/observer.html
Demonstrates how to define consumer groups for subscription and unsubscription using the `@observed_handler.groups_for_consumer` decorator. This example targets school and classroom specific groups.
```python
@classroom_change_handler.groups_for_consumer
def classroom_change_handler(self, school=None, classroom=None, **kwargs):
# This is called when you subscribe/unsubscribe
if school is not None:
yield f'-school__{school.pk}'
if classroom is not None:
yield f'-pk__{classroom.pk}'
@action()
async def subscribe_to_classrooms_in_school(self, school_pk, request_id, **kwargs):
# check user has permission to do this
await self.classroom_change_handler.subscribe(school=school, request_id=request_id)
@action()
async def subscribe_to_classroom(self, classroom_pk, request_id, **kwargs):
# check user has permission to do this
```
--------------------------------
### Create a Comment Instance (Django Shell)
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/examples/model_observer.html
Example of creating a new Comment instance within the Django shell to trigger a WebSocket message. Assumes User with pk=1 exists.
```python
>>> from my_app.models import User, Comment
>>> user_1 = User.objects.get(pk=1)
>>> user_2 = User.objects.get(pk=2)
>>> Comment.objects.create(text="user 1 creates a new comment", user=user_1)
```
--------------------------------
### Define a Consumer with Actions
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_sources/introduction.rst.txt
Example of defining a consumer class inheriting from AsyncAPIConsumer and adding an action method. This is useful for defining API endpoints within your consumer.
```python
#! consumers.py
from djangochannelsrestframework.decorators import action
from djangochannelsrestframework.consumers import AsyncAPIConsumer
class MyConsumer(AsyncAPIConsumer):
@action(detached=True)
async def send_invite_emails(self, request_id, user_pk, **kwargs):
...
```
--------------------------------
### Create a Second Comment Instance (Django Shell)
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/examples/model_observer.html
Example of creating another Comment instance with a different user in the Django shell. This will also trigger a WebSocket message.
```python
>>> Comment.objects.create(text="user 2 creates a second comment", user=user_2)
```
--------------------------------
### DeleteModelMixin Client-Side Example
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/mixins.html
Client-side JavaScript code to send a delete request to a consumer using DeleteModelMixin. Demonstrates sending data and expected response format.
```javascript
// html
const ws = new WebSocket("ws://localhost:8000/ws/")
ws.send(JSON.stringify({
action: "delete",
request_id: new Date().getTime(),
pk: 1,
}))
/* The response will be something like this.
{
"action": "delete",
"errors": [],
"response_status": 204,
"request_id": 150000,
"data": null,
}
*/
```
--------------------------------
### Project Directory Structure
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_sources/tutorial/part_1.rst.txt
This is the expected directory tree after completing the Channels Tutorial, with new Python files for the chat application.
```text
mysite/
manage.py
mysite/
__init__.py
asgi.py
settings.py
urls.py
wsgi.py
chat/
__init__.py
consumers.py
models.py
serializers.py
routing.py
templates/
chat/
index.html
room.html
tests.py
urls.py
views.py
```
--------------------------------
### RoomConsumer with CreateModelMixin
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/tutorial/part_2.html
Initializes RoomConsumer with CreateModelMixin and ObserverModelInstanceMixin for room management.
```python
from djangochannelsrestframework.mixins import CreateModelMixin
class RoomConsumer(CreateModelMixin, ObserverModelInstanceMixin, GenericAsyncAPIConsumer):
# ....
```
--------------------------------
### Get Serializer Class
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/generics.html
Retrieves the serializer class for the view. Asserts that a serializer_class is defined or overridden.
```python
def get_serializer_class(self):
"""
Return the class to be used for serialization.
By default, this is self.serializer_class, but it may be
overridden to provide different serializations depending on the
incoming request.
(Eg. admins get full serialization, others get basic serialization)
Args:
kwargs: keyworded dictionary arguments.
Returns:
Model serializer class.
"""
assert self.serializer_class is not None, (
"'%s' should either include a `serializer_class` attribute, "
"or override the `get_serializer_class()` method." % self.__class__.__name__
)
return self.serializer_class
```
--------------------------------
### Get Serializer Context
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/generics.html
Provides extra context to the serializer class, including the scope and the consumer instance.
```python
def get_serializer_context(self, **kwargs) -> Dict[str, Any]:
"""
Extra context provided to the serializer class.
Args:
kwargs: keyworded dictionary arguments.
Returns:
Context dictionary, containing the scope and the consumer instance.
"""
return {"scope": self.scope, "consumer": self}
```
--------------------------------
### Custom Permission Logic with AND, OR, NOT
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/permissions.html
Demonstrates how to combine multiple permission classes using logical operators. This allows for complex permission rules to be defined concisely.
```python
from djangochannelsrestframework.permissions import AND, OR, NOT
# Assuming MyPermission1 and MyPermission2 are custom permission classes
# permission_classes = [AND(MyPermission1, MyPermission2)]
# permission_classes = [OR(MyPermission1, MyPermission2)]
# permission_classes = [NOT(MyPermission1)]
```
--------------------------------
### Get Paginated Response Method in PaginatedModelListMixin
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/mixins.html
Generates the paginated response from serialized data. Asserts that a paginator is available.
```python
from typing import Union
from rest_framework.utils.serializer_helpers import ReturnDict, ReturnList
from collections import OrderedDict
def get_paginated_response(
self, data: Union[ReturnDict, ReturnList]
) -> OrderedDict:
assert self.paginator is not None
return self.paginator.get_paginated_response(data)
```
--------------------------------
### Paginator Property in PaginatedModelListMixin
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/mixins.html
Gets the paginator class. Returns the pagination class instance or None if pagination is disabled.
```python
from typing import Optional, Any
@property
def paginator(self) -> Optional[Any]:
"""Gets the paginator class
Returns:
Pagination class. Optional.
"""
if not hasattr(self, "_paginator"):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
return self._paginator
```
--------------------------------
### AllowAny Permission
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/permissions.html
A built-in permission class that always allows access. Useful for public endpoints or initial setup.
```python
from djangochannelsrestframework.permissions import AllowAny
# permission_classes = [AllowAny]
```
--------------------------------
### RoomConsumer with Observer Subscriptions
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_sources/tutorial/part_2.rst.txt
Demonstrates how to integrate custom observer subscriptions within a RoomConsumer. This consumer subscribes to both instance changes and message activity when a user joins or leaves a room.
```python
from djangochannelsrestframework.mixins import CreateModelMixin
from djangochannelsrestframework.observers. காரணங்கள் import action
from djangochannelsrestframework.consumers import GenericAsyncAPIConsumer
from djangochannelsrestframework.observers.mixins import ObserverModelInstanceMixin
from asgiref.sync import database_sync_to_async
class RoomConsumer(CreateModelMixin, ObserverModelInstanceMixin, GenericAsyncAPIConsumer):
# ...
@action()
async def join_room(self, pk, request_id, **kwargs):
room = await database_sync_to_async(self.get_object)(pk=pk)
await self.subscribe_instance(request_id=request_id, pk=room.pk)
await self.message_activity.subscribe(room=pk, request_id=request_id)
await self.add_user_to_room(room)
@action()
async def leave_room(self, pk, **kwargs):
room = await database_sync_to_async(self.get_object)(pk=pk)
await self.unsubscribe_instance(pk=room.pk)
await self.message_activity.unsubscribe(room=room.pk)
await self.remove_user_from_room(room)
```
--------------------------------
### Implement join and leave room actions
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_sources/tutorial/part_2.rst.txt
Adds actions for users to join and leave chat rooms, managing subscriptions and user lists.
```python
from djangochannelsrestframework.mixins import CreateModelMixin
class RoomConsumer(CreateModelMixin, ObserverModelInstanceMixin, GenericAsyncAPIConsumer):
#...
@action()
async def create(self, data: dict, request_id: str, **kwargs):
response, status = await super().create(data, **kwargs)
room_pk = response["pk"]
await self.join_room(request_id=request_id, pk=room_pk)
return response, status
@action()
async def join_room(self, pk, request_id, **kwargs):
room = await database_sync_to_async(self.get_object)(pk=pk)
await self.subscribe_instance(request_id=request_id, pk=room.pk)
await self.add_user_to_room(room)
@action()
async def leave_room(self, pk, **kwargs):
room = await database_sync_to_async(self.get_object)(pk=pk)
await self.remove_user_from_room(room)
await self.unsubscribe_instance(pk=room.pk)
@database_sync_to_async
def add_user_to_room(self, room: Room):
user: User = self.scope["user"]
room.current_users.add(user)
@database_sync_to_async
def remove_user_from_room(self, room: Room):
user: User = self.scope["user"]
room.current_users.remove(user)
```
--------------------------------
### Get Serializer Class Method
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/generics.html
Determines the serializer class to be used. By default, it returns `self.serializer_class`, but can be overridden for dynamic serializer selection.
```python
def get_serializer_class(self, **kwargs) -> Type[Serializer]:
"""
Return the class to use for the serializer.
Defaults to using `self.serializer_class`.
You may want to override this if you need to provide different
```
--------------------------------
### Get Object Method
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/generics.html
Retrieves a specific object based on lookup parameters. It supports filtering the queryset and uses `get_object_or_404` for retrieval.
```python
def get_object(self, **kwargs) -> Model:
"""
Returns the object the view is displaying.
You may want to override this if you need to provide non-standard
queryset lookups. Eg if objects are referenced using multiple
keyword arguments in the url conf.
Args:
kwargs: keyworded dictionary, it can be use it for filtering the queryset.
Returns:
:obj:`Model` object class.
Examples:
>>> filtered_queryset = self.get_object(**{"field__gte": value}) # this way you could filter from the frontend.
"""
queryset = self.filter_queryset(queryset=self.get_queryset(**kwargs), **kwargs)
# Perform the lookup filtering.
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
assert lookup_url_kwarg in kwargs,
("Expected view %s to be called with a URL keyword argument "
'named "%s"'. Fix your URL conf, or set the `.lookup_field` '
"attribute on the view correctly."
% (self.__class__.__name__, lookup_url_kwarg))
filter_kwargs = {self.lookup_field: kwargs[lookup_url_kwarg]}
obj = get_object_or_404(queryset, **filter_kwargs)
# TODO check_object_permissions
return obj
```
--------------------------------
### Get Serializer Method
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/generics.html
Returns the serializer instance used for input validation and output serialization. It utilizes `get_serializer_class` and `get_serializer_context` to configure the serializer.
```python
def get_serializer(self, action_kwargs: Dict = None, *args, **kwargs) -> Serializer:
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
Args:
action_kwargs: keyworded dictionary from the action.
args: listed arguments.
kwargs: keyworded dictionary arguments.
Returns:
Model serializer.
"""
serializer_class = self.get_serializer_class(**action_kwargs)
kwargs["context"] = self.get_serializer_context(**action_kwargs)
return serializer_class(*args, **kwargs)
```
--------------------------------
### Override create action to subscribe to new rooms
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_sources/tutorial/part_2.rst.txt
Extends the default create action to automatically subscribe the consumer to the newly created room.
```python
from djangochannelsrestframework.mixins import CreateModelMixin
class RoomConsumer(CreateModelMixin, ObserverModelInstanceMixin, GenericAsyncAPIConsumer):
@action()
async def create(self, data: dict, request_id: str, **kwargs):
response, status = await super().create(data, **kwargs)
room_pk = response["pk"]
await self.subscribe_instance(request_id=request_id, pk=room_pk)
return response, status
```
--------------------------------
### Applying Permissions to Consumers
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/permissions.html
Demonstrates how to set the `permission_classes` property on an `AsyncAPIConsumer` subclass to enforce permissions.
```APIDOC
## Applying Permissions to Consumers
### Description
Permissions can be applied to `AsyncAPIConsumer` and its subclasses by setting the `permission_classes` property.
### Example
```python
from djangochannelsrestframework.consumers import AsyncAPIConsumer
from djangochannelsrestframework.permissions import IsAuthenticated
class RoomConsumer(AsyncAPIConsumer):
permission_classes = [IsAuthenticated]
```
```
--------------------------------
### Subscribe to Comment Activity with User PK
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_sources/examples/filtered_model_observer.rst.txt
This action demonstrates how to subscribe to the comment activity observer using a user's primary key when the user is not directly available in the scope. It requires importing `database_sync_to_async` and `User` model.
```python
@action()
async def subscribe_to_comment_activity(self, user_pk, **kwargs):
# We will check if the user is authenticated for subscribing.
user = await database_sync_to_async(User.objects.get)(pk=user_pk)
await self.comment_activity.subscribe(user=user)
```
--------------------------------
### BaseObserver Initialization
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/observer/base_observer.html
Initializes the BaseObserver with a function and an optional partition. It generates a stable observer ID based on partition, class name, and function module/name.
```python
import hashlib
from collections import defaultdict
from copy import deepcopy
from typing import Any, Dict, Generator, Callable, Iterable, Optional
from djangochannelsrestframework.consumers import AsyncAPIConsumer
from djangochannelsrestframework.observer.utils import ObjPartial
class BaseObserver:
"""
This is the Base Observer class that `Observer` and `ModelObserver` inherit from.
The decorators `@model_observer` and `@observer` replaced the wrapped method with an instance of these classes.
You can then access the methods of this class using the method name that you wrapped.
"""
def __init__(self, func, partition: str = "*"):
self.func = func
self._serializer = None
self._group_names_for_signal = None
self._group_names_for_consumer = None
self._stable_observer_id = (
f"{partition}-"
f"{self.__class__.__name__}-"
f"{self.func.__module__}."
f"{self.func.__name__}"
)
```
--------------------------------
### Get Queryset Method
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/generics.html
Retrieves the list of items for the consumer. It ensures the queryset is re-evaluated on each request, preventing cached results from being used across different requests.
```python
def get_queryset(self, **kwargs) -> QuerySet:
"""
Get the list of items for this view.
This must be an iterable, and may be a queryset.
Defaults to using `self.queryset`.
This method should always be used rather than accessing `self.queryset`
directly, as `self.queryset` gets evaluated only once, and those results
are cached for all subsequent requests.
You may want to override this if you need to provide different
querysets depending on the incoming request.
(Eg. return a list of items that is specific to the user)
Args:
kwargs: keyworded dictionary.
Returns:
Queryset attribute.
"""
assert self.queryset is not None,
("'%s' should either include a `queryset` attribute, "
"or override the `get_queryset()` method." % self.__class__.__name__)
queryset = self.queryset
if isinstance(queryset, QuerySet):
# Ensure queryset is re-evaluated on each request.
queryset = queryset.all()
return queryset
```
--------------------------------
### CreateModelMixin.create
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/mixins.html
Handles the creation of a new model instance. It serializes the provided data, validates it, and then saves the new instance. Returns the serialized data of the created model and a 201 status code.
```APIDOC
## CreateModelMixin.create
### Description
Handles the creation of a new model instance. It serializes the provided data, validates it, and then saves the new instance. Returns the serialized data of the created model and a 201 status code.
### Method
POST (implied by action)
### Endpoint
Not explicitly defined, but typically associated with a consumer's WebSocket endpoint.
### Parameters
#### Path Parameters
None
#### Query Parameters
None
#### Request Body
- **data** (dict) - Required - Model data to create.
- **kwargs** (dict) - Optional - Additional keyword arguments for serializer context or actions.
### Request Example
```json
{
"action": "create",
"request_id": 150060530,
"data": {
"username": "test",
"password1": "testpassword123",
"password2": "testpassword123"
}
}
```
### Response
#### Success Response (201)
- **data** (dict) - Serialized data of the created model, including its ID.
- **response_status** (int) - 201
#### Response Example
```json
{
"action": "create",
"errors": [],
"response_status": 201,
"request_id": 150060530,
"data": {
"username": "test",
"id": 42
}
}
```
```
--------------------------------
### Define an Action Method with @action
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/decorators.html
Use the @action decorator to mark a method as an action that can be called remotely. This example shows a basic async action for deleting a user.
```python
from djangochannelsrestframework.decorators import action
class MyConsumer(AsyncAPIConsumer):
@action()
async def delete_user(self, request_id, user_pk, **kwargs):
...
```
--------------------------------
### RoomConsumer with Join and Leave Actions
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/tutorial/part_2.html
Adds actions for users to join and leave chat rooms, and includes helper methods for managing user subscriptions.
```python
from djangochannelsrestframework.mixins import CreateModelMixin
class RoomConsumer(CreateModelMixin, ObserverModelInstanceMixin, GenericAsyncAPIConsumer):
#...
@action()
async def create(self, data: dict, request_id: str, **kwargs):
response, status = await super().create(data, **kwargs)
room_pk = response["pk"]
await self.join_room(request_id=request_id, pk=room_pk)
return response, status
@action()
async def join_room(self, pk, request_id, **kwargs):
room = await database_sync_to_async(self.get_object)(pk=pk)
await self.subscribe_instance(request_id=request_id, pk=room.pk)
await self.add_user_to_room(room)
@action()
async def leave_room(self, pk, **kwargs):
room = await database_sync_to_async(self.get_object)(pk=pk)
await self.remove_user_from_room(room)
await self.unsubscribe_instance(pk=room.pk)
@database_sync_to_async
def add_user_to_room(self, room: Room):
user: User = self.scope["user"]
room.current_users.add(user)
@database_sync_to_async
def remove_user_from_room(self, room: Room):
user: User = self.scope["user"]
room.current_users.remove(user)
```
--------------------------------
### BaseObserver __get__ Method
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/observer/base_observer.html
Implements descriptor protocol, returning the observer instance itself when accessed directly or an ObjPartial instance when accessed via a consumer instance.
```python
def __get__(self, parent, objtype):
if parent is None:
return self
return ObjPartial(self, consumer=parent)
```
--------------------------------
### StreamedPaginatedListMixin
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_modules/djangochannelsrestframework/mixins.html
Paginated list mixin that automatically streams extra pages. Action `list` to start streaming list pages. Action `list_cancel` will cancel all inflight lists.
```APIDOC
## list
### Description
Streams a paginated list of model instances. This method retrieves a paginated list of objects, sends the initial response, and continues fetching and streaming additional pages until all results are delivered.
### Method
POST (Implicit, due to detached=True)
### Endpoint
/
### Parameters
#### Path Parameters
- **action** (str) - The action to perform, expected to be 'list'.
- **request_id** (str) - A unique identifier for the request.
#### Query Parameters
- **kwargs** (any) - Additional keyword arguments used for pagination and filtering.
### Request Example
```json
{
"action": "list",
"request_id": "unique-request-id",
"kwargs": { ... }
}
```
### Response
#### Success Response (200)
- **data** (any) - Serialized data of the model instances for the current page.
- **status** (int) - HTTP status code, typically 200.
#### Response Example
```json
{
"example": "response body"
}
```
```
```APIDOC
## list_cancel
### Description
Action that will stop all pending streaming list requests.
### Method
POST (Implicit)
### Endpoint
/
### Parameters
#### Path Parameters
- **action** (str) - The action to perform, expected to be 'list_cancel'.
- **request_id** (str) - A unique identifier for the request.
### Request Example
```json
{
"action": "list_cancel",
"request_id": "unique-request-id"
}
```
### Response
#### Success Response (200)
- **status** (int) - HTTP status code, typically 200.
#### Response Example
```json
{
"status": 200
}
```
```
--------------------------------
### Add model_observer for message activity
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_sources/tutorial/part_2.rst.txt
Sets up a model observer to watch for new messages in a room and notify relevant consumers.
```python
from djangochannelsrestframework.mixins import CreateModelMixin
class RoomConsumer(CreateModelMixin, ObserverModelInstanceMixin, GenericAsyncAPIConsumer):
# ...
@model_observer(Message)
async def message_activity(
self,
message,
observer=None,
subscribing_request_ids=[],
**kwargs
):
"""
```
--------------------------------
### UpdateModelMixin Client-Side WebSocket Interaction
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/mixins.html
Client-side JavaScript code to establish a WebSocket connection and send an 'update' action to modify a model instance. Includes an example of the expected server response.
```javascript
const ws = new WebSocket("ws://localhost:8000/ws/")
ws.send(JSON.stringify({
action: "update",
request_id: new Date().getTime(),
pk: 1,
data: {
username: "test edited",
},
}))
/* The response will be something like this.
{
"action": "update",
"errors": [],
"response_status": 200,
"request_id": 1500000,
"data": {"email": "42@example.com", "id": 1, "username": "test edited"},
}
*/
```
--------------------------------
### Project File Structure
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_sources/examples/generic_api_consumer.rst.txt
Displays the typical file structure for a Django project utilizing Django Channels REST Framework.
```text
mysite/
manage.py
mysite/
__init__.py
asgi.py
settings.py
urls.py
wsgi.py
example/
__init__.py
consumers.py
models.py
serializers.py
routing.py
templates/
example/
index.html
tests.py
urls.py
views.py
```
--------------------------------
### PatchModelMixin Client-Side WebSocket Interaction
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/mixins.html
Client-side JavaScript code to establish a WebSocket connection and send a 'patch' action to update a model instance. Includes an example of the expected server response.
```javascript
const ws = new WebSocket("ws://localhost:8000/ws/")
ws.send(JSON.stringify({
action: "patch",
request_id: new Date().getTime(),
pk: 1,
data: {
email: "00@example.com",
},
}))
/* The response will be something like this.
{
"action": "patch",
"errors": [],
"response_status": 200,
"request_id": 150000,
"data": {"email": "00@example.com", "id": 1, "username": "test1"},
}
*/
```
--------------------------------
### Implement create_message action
Source: https://djangochannelsrestframework.readthedocs.io/en/latest/_sources/tutorial/part_2.rst.txt
Defines an action to create a new message within a specified room.
```python
from djangochannelsrestframework.mixins import CreateModelMixin
class RoomConsumer(CreateModelMixin, ObserverModelInstanceMixin, GenericAsyncAPIConsumer):
# ...
@action()
async def create_message(self, message, room, **kwargs):
room: Room = await database_sync_to_async(self.get_object)(pk=room)
await database_sync_to_async(Message.objects.create)(
room=room,
user=self.scope["user"],
text=message
)
```