All Projects → hishnash → Djangochannelsrestframework

hishnash / Djangochannelsrestframework

Licence: mit
A Rest-framework for websockets using Django channels-v3

Programming Languages

python
139335 projects - #7 most used programming language

Projects that are alternatives of or similar to Djangochannelsrestframework

Graphene Django Subscriptions
This package adds support to Subscription's requests and its integration with websockets using Channels package.
Stars: ✭ 173 (-22.77%)
Mutual labels:  channels, django
Drf Yasg
Automated generation of real Swagger/OpenAPI 2.0 schemas from Django REST Framework code.
Stars: ✭ 2,523 (+1026.34%)
Mutual labels:  django, django-rest-framework
Crud App Vuejs Django
This is simple crud app and searchFilter made using vuejs and django. Used to explain the tutorial present on https://medium.com/@shubhambansal_89125/crud-app-using-vue-js-and-django-516edf4e4217 https://medium.com/@shubhambansal_89125/searchfilter-using-django-and-vue-js-215af82e12cd
Stars: ✭ 174 (-22.32%)
Mutual labels:  django, django-rest-framework
Djangorestframework Queryfields
Allows clients to control which fields will be sent in the API response
Stars: ✭ 170 (-24.11%)
Mutual labels:  django, django-rest-framework
Vecihi
Build Your Own Photo Sharing App in 5 minutes
Stars: ✭ 199 (-11.16%)
Mutual labels:  django, django-rest-framework
Django Antd Tyadmin
类似 xadmin 的基于Model 快速生成前后台管理增删改查,筛选,搜索的后台管理自动化工具。Antd 界面好看现代化!前后端分离!无损二次开发!由Django Restful Framework 和 Ant Design Pro V4 驱动
Stars: ✭ 171 (-23.66%)
Mutual labels:  django, django-rest-framework
Django Enumfield
Custom Django field for using enumerations of named constants
Stars: ✭ 184 (-17.86%)
Mutual labels:  django, django-rest-framework
Django Guid
Inject an ID into every log message from a Django request. ASGI compatible, integrates with Sentry, and works with Celery
Stars: ✭ 166 (-25.89%)
Mutual labels:  django, django-rest-framework
Django Rest Auth
This app makes it extremely easy to build Django powered SPA's (Single Page App) or Mobile apps exposing all registration and authentication related functionality as CBV's (Class Base View) and REST (JSON)
Stars: ✭ 2,289 (+921.88%)
Mutual labels:  django, django-rest-framework
Rengorum
🚀 Forum app built in React, Redux & Django
Stars: ✭ 194 (-13.39%)
Mutual labels:  django, django-rest-framework
Rest Api Basics
This is a basic guide on how to build a REST API with Django & Python. For much deeper depth, check out our new course on REST API: (https://kirr.co/90kxtx)
Stars: ✭ 171 (-23.66%)
Mutual labels:  django, django-rest-framework
Blogbackendproject
Backend code for my blogs, develop with Django Rest framework.
Stars: ✭ 204 (-8.93%)
Mutual labels:  django, django-rest-framework
Vue People
VuePeople lists and connects Vue.JS developers around the world.
Stars: ✭ 167 (-25.45%)
Mutual labels:  django, django-rest-framework
Treeherder
A system for managing CI data for Mozilla projects
Stars: ✭ 212 (-5.36%)
Mutual labels:  django, django-rest-framework
Usaspending Api
Server application to serve U.S. federal spending data via a RESTful API
Stars: ✭ 166 (-25.89%)
Mutual labels:  django, django-rest-framework
Django Rest Framework Serializer Extensions
Extensions to help DRY up Django Rest Framework serializers
Stars: ✭ 180 (-19.64%)
Mutual labels:  django, django-rest-framework
Django Grpc Framework
gRPC for Django.
Stars: ✭ 162 (-27.68%)
Mutual labels:  django, django-rest-framework
Visual Chatbot
☁️ 👀 💬 Visual Chatbot
Stars: ✭ 161 (-28.12%)
Mutual labels:  channels, django
Djangorestframework Stubs
PEP-484 stubs for django-rest-framework
Stars: ✭ 191 (-14.73%)
Mutual labels:  django, django-rest-framework
Drf Access Policy
Declarative access policies/permissions modeled after AWS' IAM policies.
Stars: ✭ 200 (-10.71%)
Mutual labels:  django, django-rest-framework

============================== Django Channels Rest Framework

Django Channels Rest Framework provides a DRF like interface for building channels-v3_ websocket consumers.

This project can be used alongside HyperMediaChannels_ and ChannelsMultiplexer_ to create a Hyper Media Style api over websockets. However Django Channels Rest Framework is also a free standing framework with the goal of providing an api that is familiar to DRF users.

theY4Kman_ has developed a useful Javascript client library dcrf-client_ to use with DCRF.

.. image:: https://travis-ci.org/hishnash/djangochannelsrestframework.svg?branch=master :target: https://travis-ci.org/hishnash/djangochannelsrestframework

Thanks to

DCRF is based of a fork of Channels Api <https://github.com/linuxlewis/channels-api>_ and of course inspired by Django Rest Framework <http://www.django-rest-framework.org/>_.

Install

.. code-block:: bash

pip install djangochannelsrestframework

.. warning ::

		In your application definition when you declare your consumers it is very important to use the `.as_asgi()` class method. Eg `MyConsumer.as_asgi()` you **should not** have any instances of `MyConsumer()` in your code base.

A Generic Api Consumer

In DCRF you can create a GenericAsyncAPIConsumer that works much like a GenericAPIView_ in DRF: For a more indeph look into Rest Like Websocket consumers read this blog post_.

.. code-block:: python

from . import models
from . import serializers
from djangochannelsrestframework import permissions
from djangochannelsrestframework.generics import GenericAsyncAPIConsumer
from djangochannelsrestframework.mixins import (
    ListModelMixin,
    PatchModelMixin,
    UpdateModelMixin,
    CreateModelMixin,
    DeleteModelMixin,
)

class LiveConsumer(ListModelMixin, GenericAsyncAPIConsumer):
    queryset = models.Test.objects.all()
    serializer_class = serializers.TestSerializer
    permission_classes = (permissions.IsAuthenticated,)

Because this class uses the ListModelMixin, one has access to the list action.

One may use the same exact querysets and serializer_class utilized in their DRF Views, but must omit the DRF permissions. Permissions are to be imported from djangochannelsrestframework, which provides the standard AllowAny and IsAuthenticated permissions.

To call an action from the client send a websocket message: {action: "list", "request_id": 42}

There are a selection of mixins that expose the common CURD actions:

  • ListModelMixin - list
  • PatchModelMixin - patch
  • CreateModelMixin - create
  • RetrieveModelMixin - retrieve
  • UpdateModelMixin - update
  • DeleteModelMixin - delete

Observing a Model instance

Consumer that let you subscribe to changes on an instance:

.. code-block:: python

class TestConsumer(ObserverModelInstanceMixin, GenericAsyncAPIConsumer): queryset = get_user_model().objects.all() serializer_class = UserSerializer

this exposes the retrieve, subscribe_instance and unsubscribe_instance actions.

To subscribe send:

.. code-block:: python

{ "action": "subscribe_instance", "pk": 42, # the id of the instance you are subscribing to "request_id": 4 # this id will be used for all resultent updates. }

Actions will be sent down out from the server:

.. code-block:: python

{ "action": "update", "errors": [], "response_status": 200, "request_id": 4, "data": {'email': '[email protected]', 'id': 42, 'username': 'thenewname'}, }

Adding Custom actions

.. code-block:: python

class UserConsumer(GenericAsyncAPIConsumer): queryset = get_user_model().objects.all() serializer_class = UserSerializer

   @action()
   async def send_email(self, pk=None, to=None, **kwargs):
       user = await database_sync_to_async(self.get_object)(pk=pk)
       # ... do some stuff
       # remember to wrap all db actions in `database_sync_to_async`
       return {}, 200  # return the contenct and the response code.

   @action()  # if the method is not async it is already wrapped in `database_sync_to_async`
   def publish(self, pk=None, **kwargs):
       user = self.get_object(pk=pk)
       # ...
       return {'pk': pk}, 200

Consumers that are not bound to Models

You can also create consumers that are not at all related to any models.

.. code-block:: python

from djangochannelsrestframework.decorators import action from djangochannelsrestframework.consumers import AsyncAPIConsumer

class MyConsumer(AsyncAPIConsumer):

  @action()
  async def an_async_action(self, some=None, **kwargs):
      # do something async
      return {'response with': 'some message'}, 200
  
  @action()
  def a_sync_action(self, pk=None, **kwargs):
      # do something sync
      return {'response with': 'some message'}, 200

Using your normal views over a websocket connection

.. code-block:: python

from djangochannelsrestframework.consumers import view_as_consumer

application = ProtocolTypeRouter({ "websocket": AuthMiddlewareStack( URLRouter([ url(r"^front(end)/$", view_as_consumer(YourDjangoView)), ]) ), })

Subscribing to all instances of a model

One can subscribe to all instances of a model by utilizing the model_observer.

.. code-block:: python

from djangochannelsrestframework.observer import model_observer

@model_observer(models.Test)
async def model_activity(self, message, observer=None, action=None, **kwargs):
    # send activity to your frontend
    await self.send_json(message)

This method will send messages to the client on all CRUD operations made through the Django ORM. The action arg here it will take values such as create, delete and update you should consider passing this to your frontend client.

Note: These notifications do not include bulk updates, such as models.Test.objects.filter(name="abc").update(name="newname")

**WARNING**
When using this to decorate a method to avoid the method firing multiple
times you should ensure that if there are multiple `@model_observer`
wrapped methods for the same model type within a single file that each
method has a different name.

Subscribing to a model_observer

You can do this in a few placed, a common example is in the websocket_connect method.

.. code-block:: python

async def websocket_connect(self, message):

    # Super Save
    await super().websocket_connect(message)

    # Initialized operation
    await self.activities_change.subscribe()

This method utilizes the previously mentioned model_activity method to subscribe to all instances of the current Consumer's model.

One can also subscribe by creating a custom action

Another way is override AsyncAPIConsumer.accept(self, **kwargs)

.. code-block:: python

class ModelConsumerObserver(AsyncAPIConsumer):
    async def accept(self, **kwargs):
        await super().accept(** kwargs)
        await self.model_change.subscribe()
    

    @model_observer(models.Test)
    async def model_change(self, message, action=None, **kwargs):
        await self.send_json(message)
    
    ''' If you want the data serializeded instead of pk '''
    @model_change.serializer
    def model_serialize(self, instance, action, **kwargs):
        return TestSerializer(instance).data

Subscribing to a filtered list of models

In most situations you want to filter the set of models that you subscribe to.

To do this we need to split the model updates into groups and then in the consumer subscribe to the groups that we want/have permission to see.

.. code-block:: python

class MyConsumer(AsyncAPIConsumer):

@model_observer(models.Classroom)
async def classroom_change_handler(self, message, observer=None, action=None, **kwargs):
    # due to not being able to make DB QUERIES when selecting a group
    # maybe do an extra check here to be sure the user has permission
    # send activity to your frontend
    await self.send_json(dict(body=message, action=action))

@classroom_change_handler.groups_for_signal
def classroom_change_handler(self, instance: models.Classroom, **kwargs):
    # this block of code is called very often *DO NOT make DB QUERIES HERE*
    yield f'-school__{instance.school_id}'
    yield f'-pk__{instance.pk}'

@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, **kwargs):
    # check user has permission to do this
    await self.classroom_change_handler.subscribe(school=school)

@action()
async def subscribe_to_classroom(self, classroom_pk, **kwargs):
    # check user has permission to do this
    await self.classroom_change_handler.subscribe(classroom=classroom)

.. _post: https://lostmoa.com/blog/DjangoChannelsRestFramework/ .. _GenericAPIView: https://www.django-rest-framework.org/api-guide/generic-views/ .. _channels-v3: https://channels.readthedocs.io/en/latest/ .. _dcrf-client: https://github.com/theY4Kman/dcrf-client .. _theY4Kman: https://github.com/theY4Kman .. _HyperMediaChannels: https://github.com/hishnash/hypermediachannels .. _ChannelsMultiplexer: https://github.com/hishnash/channelsmultiplexer

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].