Skip to main content

Graphene-Django-Subscriptions add subscriptions support to graphene-django through Channels module

Project description

This package adds support to Subscription’s requests and its integration with websockets using Channels package. You can test websockets notifications with this mini web tool. It’s intuitive and simple: websocket_example_client

Installation:

For installing graphene-django-subscriptions, just run this command in your shell:

pip install "graphene-django-subscriptions"

Documentation:

Extra functionalities (Subscriptions):

  1. Subscription (Abstract class to define subscriptions to a DjangoSerializerMutation)

  2. GraphqlAPIDemultiplexer (Custom WebSocket consumer subclass that handles demultiplexing streams)

Subscriptions:

This first approach to add Graphql subscriptions support with Channels in graphene-django, use channels-api package.

1- Defining custom Subscriptions classes:

You must to have defined a Serializer class for each model that you want to define a Subscription class:

# app/graphql/subscriptions.py
import graphene
from graphene_django_subscriptions.subscription import Subscription
from .serializers import UserSerializer, GroupSerializer


class UserSubscription(Subscription):
    class Meta:
        serializer_class = UserSerializer
        stream = 'users'
        description = 'User Subscription'


class GroupSubscription(Subscription):
    class Meta:
        serializer_class = GroupSerializer
        stream = 'groups'
        description = 'Group Subscription'

Add the subscriptions definitions into your app’s schema:

# app/graphql/schema.py
import graphene
from .subscriptions import UserSubscription, GroupSubscription


class Subscriptions(graphene.ObjectType):
    user_subscription = UserSubscription.Field()
    GroupSubscription = PersonSubscription.Field()

Add the app’s schema into your project root schema:

# schema.py
import graphene
import custom.app.route.graphql.schema


class RootQuery(custom.app.route.graphql.schema.Query, graphene.ObjectType):
    class Meta:
        description = 'The project root query definition'


class RootMutation(custom.app.route.graphql.schema.Mutation, graphene.ObjectType):
    class Meta:
        description = 'The project root mutation definition'


class RootSubscription(custom.app.route.graphql.schema.Subscriptions, graphene.ObjectType):
    class Meta:
        description = 'The project root subscription definition'


schema = graphene.Schema(
    query=RootQuery,
    mutation=RootMutation,
    subscription=RootSubscription
)

2- Defining Channels settings and custom routing config:

Note: For more information about this step see Channels documentation.

You must to have defined a DjangoSerializerMutation class for each model that you want to define a Subscription class:

We define app routing, as if they were app urls:

# app/routing.py
from graphene_django_subscriptions.consumers import GraphqlAPIDemultiplexer
from channels.routing import route_class
from .graphql.subscriptions import UserSubscription, GroupSubscription


class CustomAppDemultiplexer(GraphqlAPIDemultiplexer):
    consumers = {
      'users': UserSubscription.get_binding().consumer,
      'groups': GroupSubscription.get_binding().consumer
    }


app_routing = [
    route_class(CustomAppDemultiplexer)
]

Defining our project routing, like custom root project urls:

# project/routing.py
from channels import include

project_routing = [
    include("custom.app.folder.routing.app_routing", path=r"^/custom_websocket_path"),
]

You should put into your INSTALLED_APPS the channels and channels_api modules and you must to add your project’s routing definition into the CHANNEL_LAYERS setting:

# settings.py
...
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    ...
    'channels',
    'channels_api',

    'custom_app'
)

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "asgiref.inmemory.ChannelLayer",
        "ROUTING": "myproject.routing.project_routing",  # Our project routing
    },
}
...

You must add ‘graphene_django_subscriptions.SubscriptionMiddleware’ middleware at the end of your GRAPHENE dict config on your settings.py:

# settings.py
...
GRAPHENE = {
    'SCHEMA_INDENT': 4,
    'MIDDLEWARE': [
        # Others middleware
        'graphene_django_subscriptions.SubscriptionMiddleware',
    ]
}
...

3- Subscription’s examples:

In your WEB client you must define websocket connection to: ‘ws://host:port/custom_websocket_path’. When the connection is established, the server return a websocket’s message like this: {“channel_id”: “GthKdsYVrK!WxRCdJQMPi”, “connect”: “success”}, where you must store the channel_id value to later use in your graphql subscriptions request for subscribe or unsubscribe operations.

The graphql’s subscription request accept five possible parameters: 1. operation: Operation to perform: subscribe or unsubscribe. (required) 2. action: Action to which you wish to subscribe: create, update, delete or all_actions. (required) 3. channelId: Identification of the connection by websocket. (required) 4. id: Object’s ID field value that you wish to subscribe to. (optional) 5. data: Model’s fields that you want to appear in the subscription notifications. (optional)

subscription{
    userSubscription(
        action: UPDATE,
        operation: SUBSCRIBE,
        channelId: "GthKdsYVrK!WxRCdJQMPi",
        id: 5,
        data: [ID, USERNAME, FIRST_NAME, LAST_NAME, EMAIL, IS_SUPERUSER]
    ){
        ok
        error
        stream
    }
}

In this case, the subscription request sent return a websocket message to client like this: {“action”: “update”, “operation”: “subscribe”, “ok”: true, “stream”: “users”, “error”: null} and from that moment each time than the user with id=5 get modified, you will receive a message through websocket’s connection with the following format:

{
    "stream": "users",
    "payload": {
        "action": "update",
        "model": "auth.user",
        "data": {
            "id": 5,
            "username": "meaghan90",
            "first_name": "Meaghan",
            "last_name": "Ackerman",
            "email": "meaghan@gmail.com",
            "is_superuser": false
        }
    }
}

For unsubscribe you must send a graphql request like this:

subscription{
    userSubscription(
        action: UPDATE,
        operation: UNSUBSCRIBE,
        channelId: "GthKdsYVrK!WxRCdJQMPi",
        id: 5
    ){
        ok
        error
        stream
    }
}

NOTE: Each time than the graphql’s server restart, you must to reestablish the websocket connection and resend the graphql’s subscription request with the new websocket connection id.

Change Log:

v0.0.9:

  1. Fixed minor bugs.

v0.0.6:

  1. Fixed minor bug on model_fields_enum generation when define fields in serializer class like this: fields = “__all__”

  2. This avoid malfunction with the posterior versions of graphene-django.

v0.0.4:

  1. Fixed minor bug on subscription_resolver function.

v0.0.3:

  1. Added depromise_subscription middleware to allow use subscriptions on graphene-django>=2.0.

  2. Updated setup dependence to graphene-django-extras>=0.3.0.

v0.0.2:

1. Changed mutation_class dependence on Subscription Meta class definition to serializer_class to get better integration. 2. Fixed some minor bugs.

v0.0.1:

  1. First commit

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

graphene_django_subscriptions-0.0.9.tar.gz (10.4 kB view details)

Uploaded Source

Built Distribution

graphene_django_subscriptions-0.0.9-py2.py3-none-any.whl (9.7 kB view details)

Uploaded Python 2 Python 3

File details

Details for the file graphene_django_subscriptions-0.0.9.tar.gz.

File metadata

  • Download URL: graphene_django_subscriptions-0.0.9.tar.gz
  • Upload date:
  • Size: 10.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.41.1 CPython/3.7.4

File hashes

Hashes for graphene_django_subscriptions-0.0.9.tar.gz
Algorithm Hash digest
SHA256 37776e5a766323234ca1790c1ef269a692890ac68ec4c3e4c1eb6b83e2e46710
MD5 18f0112b3d376b7a3db5ff2cb2e9336b
BLAKE2b-256 e8b9740530d50046e884b086b3c99cfbcd6697a5ea6640787a323e24300dcf70

See more details on using hashes here.

File details

Details for the file graphene_django_subscriptions-0.0.9-py2.py3-none-any.whl.

File metadata

  • Download URL: graphene_django_subscriptions-0.0.9-py2.py3-none-any.whl
  • Upload date:
  • Size: 9.7 kB
  • Tags: Python 2, Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/3.1.1 pkginfo/1.5.0.1 requests/2.22.0 setuptools/40.8.0 requests-toolbelt/0.9.1 tqdm/4.41.1 CPython/3.7.4

File hashes

Hashes for graphene_django_subscriptions-0.0.9-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 1566f92c7002b5c9735d3a9e29747abeed9651c79c793ffeb882100fa904268a
MD5 bccd6578605d5aa02f3e854193fa804e
BLAKE2b-256 31fe42870e3f0fe80ba4e0ebc7b1f093f794fe964ad4060865e277eb96a21e18

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page