### 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
        )

```