{ "info": { "author": "Ernesto Perez Amigo", "author_email": "eamigo@nauta.cu", "bugtrack_url": null, "classifiers": [ "Intended Audience :: Developers", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: Implementation :: PyPy", "Topic :: Software Development :: Libraries" ], "description": "Graphene-Django-Subscriptions\n=============================\n\nThis 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 `_\n\n\nInstallation:\n-------------\n\nFor installing graphene-django-subscriptions, just run this command in your shell:\n\n.. code:: bash\n\n pip install \"graphene-django-subscriptions\"\n\nDocumentation:\n--------------\n\n***************************************\nExtra functionalities (Subscriptions):\n***************************************\n 1. Subscription (Abstract class to define subscriptions to a DjangoSerializerMutation)\n 2. GraphqlAPIDemultiplexer (Custom WebSocket consumer subclass that handles demultiplexing streams)\n\n\nSubscriptions:\n--------------\n\nThis first approach to add Graphql subscriptions support with Channels in graphene-django, use channels-api package.\n\n*****************************************\n1- Defining custom Subscriptions classes:\n*****************************************\n\nYou must to have defined a Serializer class for each model that you want to define a Subscription class:\n\n.. code:: python\n\n # app/graphql/subscriptions.py\n import graphene\n from graphene_django_subscriptions.subscription import Subscription\n from .serializers import UserSerializer, GroupSerializer\n\n\n class UserSubscription(Subscription):\n class Meta:\n serializer_class = UserSerializer\n stream = 'users'\n description = 'User Subscription'\n\n\n class GroupSubscription(Subscription):\n class Meta:\n serializer_class = GroupSerializer\n stream = 'groups'\n description = 'Group Subscription'\n\n\nAdd the subscriptions definitions into your app's schema:\n\n.. code:: python\n\n # app/graphql/schema.py\n import graphene\n from .subscriptions import UserSubscription, GroupSubscription\n\n\n class Subscriptions(graphene.ObjectType):\n user_subscription = UserSubscription.Field()\n GroupSubscription = PersonSubscription.Field()\n\n\nAdd the app's schema into your project root schema:\n\n.. code:: python\n\n # schema.py\n import graphene\n import custom.app.route.graphql.schema\n\n\n class RootQuery(custom.app.route.graphql.schema.Query, graphene.ObjectType):\n class Meta:\n description = 'The project root query definition'\n\n\n class RootMutation(custom.app.route.graphql.schema.Mutation, graphene.ObjectType):\n class Meta:\n description = 'The project root mutation definition'\n\n\n class RootSubscription(custom.app.route.graphql.schema.Subscriptions, graphene.ObjectType):\n class Meta:\n description = 'The project root subscription definition'\n\n\n schema = graphene.Schema(\n query=RootQuery,\n mutation=RootMutation,\n subscription=RootSubscription\n )\n\n\n********************************************************\n2- Defining Channels settings and custom routing config:\n********************************************************\n**Note**: For more information about this step see Channels documentation.\n\nYou must to have defined a DjangoSerializerMutation class for each model that you want to define a Subscription class:\n\nWe define app routing, as if they were app urls:\n\n.. code:: python\n\n # app/routing.py\n from graphene_django_subscriptions.consumers import GraphqlAPIDemultiplexer\n from channels.routing import route_class\n from .graphql.subscriptions import UserSubscription, GroupSubscription\n\n\n class CustomAppDemultiplexer(GraphqlAPIDemultiplexer):\n consumers = {\n 'users': UserSubscription.get_binding().consumer,\n 'groups': GroupSubscription.get_binding().consumer\n }\n\n\n app_routing = [\n route_class(CustomAppDemultiplexer)\n ]\n\n\nDefining our project routing, like custom root project urls:\n\n.. code:: python\n\n # project/routing.py\n from channels import include\n\n project_routing = [\n include(\"custom.app.folder.routing.app_routing\", path=r\"^/custom_websocket_path\"),\n ]\n\n\nYou 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:\n\n.. code:: python\n\n # settings.py\n ...\n INSTALLED_APPS = (\n 'django.contrib.auth',\n 'django.contrib.contenttypes',\n 'django.contrib.sessions',\n 'django.contrib.sites',\n ...\n 'channels',\n 'channels_api',\n\n 'custom_app'\n )\n\n CHANNEL_LAYERS = {\n \"default\": {\n \"BACKEND\": \"asgiref.inmemory.ChannelLayer\",\n \"ROUTING\": \"myproject.routing.project_routing\", # Our project routing\n },\n }\n ...\n\nYou must add **'graphene_django_subscriptions.depromise_subscription'** middleware at the end of your GRAPHENE dict config on your settings.py:\n\n.. code:: python\n\n # settings.py\n ...\n GRAPHENE = {\n 'SCHEMA_INDENT': 4,\n 'MIDDLEWARE': [\n # Others middleware\n 'graphene_django_subscriptions.depromise_subscription',\n ]\n }\n ...\n\n\n***************************\n3- Subscription's examples:\n***************************\n\nIn your WEB client you must define websocket connection to: 'ws://host:port/custom_websocket_path'.\nWhen the connection is established, the server return a websocket's message like this:\n{\"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.\n\nThe graphql's subscription request accept five possible parameters:\n1. **operation**: Operation to perform: subscribe or unsubscribe. (required)\n2. **action**: Action to which you wish to subscribe: create, update, delete or all_actions. (required)\n3. **channelId**: Identification of the connection by websocket. (required)\n4. **id**: Object's ID field value that you wish to subscribe to. (optional)\n5. **data**: Model's fields that you want to appear in the subscription notifications. (optional)\n\n.. code:: python\n\n subscription{\n userSubscription(\n action: UPDATE,\n operation: SUBSCRIBE,\n channelId: \"GthKdsYVrK!WxRCdJQMPi\",\n id: 5,\n data: [ID, USERNAME, FIRST_NAME, LAST_NAME, EMAIL, IS_SUPERUSER]\n ){\n ok\n error\n stream\n }\n }\n\n\nIn 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:\n\n.. code:: python\n\n {\n \"stream\": \"users\",\n \"payload\": {\n \"action\": \"update\",\n \"model\": \"auth.user\",\n \"data\": {\n \"id\": 5,\n \"username\": \"meaghan90\",\n \"first_name\": \"Meaghan\",\n \"last_name\": \"Ackerman\",\n \"email\": \"meaghan@gmail.com\",\n \"is_superuser\": false\n }\n }\n }\n\n\nFor unsubscribe you must send a graphql request like this:\n\n.. code:: python\n\n subscription{\n userSubscription(\n action: UPDATE,\n operation: UNSUBSCRIBE,\n channelId: \"GthKdsYVrK!WxRCdJQMPi\",\n id: 5\n ){\n ok\n error\n stream\n }\n }\n\n\n*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.\n\n\nChange Log:\n-----------\n\n*******\nv0.0.6:\n*******\n1. Fixed minor bug on model_fields_enum generation when define fields in serializer class like this: fields = \"__all__\"\n2. This avoid malfunction with the posterior versions of graphene-django.\n\n*******\nv0.0.4:\n*******\n1. Fixed minor bug on *subscription_resolver* function.\n\n*******\nv0.0.3:\n*******\n1. Added **depromise_subscription** middleware to allow use subscriptions on graphene-django>=2.0.\n2. Updated setup dependence to graphene-django-extras>=0.3.0.\n\n*******\nv0.0.2:\n*******\n1. Changed mutation_class dependence on Subscription Meta class definition to serializer_class to get better\nintegration.\n2. Fixed some minor bugs.\n\n*******\nv0.0.1:\n*******\n1. First commit\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/eamigo86/graphene-django-subscriptions", "keywords": "api graphql subscription rest graphene django channels", "license": "MIT", "maintainer": "", "maintainer_email": "", "name": "graphene-django-subscriptions", "package_url": "https://pypi.org/project/graphene-django-subscriptions/", "platform": "any", "project_url": "https://pypi.org/project/graphene-django-subscriptions/", "project_urls": { "Homepage": "https://github.com/eamigo86/graphene-django-subscriptions" }, "release_url": "https://pypi.org/project/graphene-django-subscriptions/0.0.6/", "requires_dist": [ "graphene-django (==2.0.0)", "graphene-django-extras (>=0.3.0)", "channels-api (>=0.4.0)" ], "requires_python": "", "summary": "Graphene-Django-Subscriptions add subscriptions support to graphene-django through Channels module", "version": "0.0.6" }, "last_serial": 4776853, "releases": { "0.0.1": [ { "comment_text": "", "digests": { "md5": "b21333c925b03e67110403721634691f", "sha256": "8b9dcbfcef52abbe3a676ac755c20f40e3ee5c3b997db7f94f346e3724bddcee" }, "downloads": -1, "filename": "graphene_django_subscriptions-0.0.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "b21333c925b03e67110403721634691f", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 11263, "upload_time": "2017-11-06T15:51:15", "url": "https://files.pythonhosted.org/packages/82/90/267a87c046072b184d44b3001c7361ed6e64ac02acbb47234476dfbc4ad2/graphene_django_subscriptions-0.0.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f826d7e061d2f7a4ed7a6f08b977fbc2", "sha256": "06bd1b64a36f8e69f56c11e70866ff561f4da27bc7e5c3bdaf5cc08452e9b4a6" }, "downloads": -1, "filename": "graphene_django_subscriptions-0.0.1.tar.gz", "has_sig": false, "md5_digest": "f826d7e061d2f7a4ed7a6f08b977fbc2", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 8788, "upload_time": "2017-11-06T15:51:29", "url": "https://files.pythonhosted.org/packages/f3/7d/0656212c1ab1c4439de491e1541c2bdfe6d12e003564b61add90a698e0c1/graphene_django_subscriptions-0.0.1.tar.gz" } ], "0.0.2": [ { "comment_text": "", "digests": { "md5": "b7a320967c22aa3827dbf76fe91dfb43", "sha256": "88e2ce18311b6847826c4baa8754e9bbd137171dd5bd8d6ac7f64f01372e5f31" }, "downloads": -1, "filename": "graphene_django_subscriptions-0.0.2-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "b7a320967c22aa3827dbf76fe91dfb43", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 11568, "upload_time": "2017-12-20T20:44:04", "url": "https://files.pythonhosted.org/packages/26/70/eb328089acd71a2479165ebbc8ed4860f1354587910feaa9842195fc6c55/graphene_django_subscriptions-0.0.2-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f852178166f2301fb7ec89aa65c14321", "sha256": "375d41ab25f001ebf81490b63964231d9c6cea390f07a63610413584d391e21f" }, "downloads": -1, "filename": "graphene_django_subscriptions-0.0.2.tar.gz", "has_sig": false, "md5_digest": "f852178166f2301fb7ec89aa65c14321", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9008, "upload_time": "2017-12-20T20:44:06", "url": "https://files.pythonhosted.org/packages/06/ec/9cd0ad197d4c7931042b5ae12edfd058e2852930815a4726ef8d24582e34/graphene_django_subscriptions-0.0.2.tar.gz" } ], "0.0.3": [ { "comment_text": "", "digests": { "md5": "27be97f69b4fedf951e52ea813d38cda", "sha256": "dccee7f7bf0e8bb1605579c158d52ae32c291ef7efd78f5a2436723a2ca3dbb6" }, "downloads": -1, "filename": "graphene_django_subscriptions-0.0.3-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "27be97f69b4fedf951e52ea813d38cda", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 12180, "upload_time": "2018-01-05T23:02:55", "url": "https://files.pythonhosted.org/packages/21/a6/791ba61be8a67e9eab1ac8493d0b7bf45ac0d4f9a2690e1977fbc6632375/graphene_django_subscriptions-0.0.3-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "2917ce27abb86bbc6ce4d93f47366517", "sha256": "7c92270f90ca28c7b0bb07c574764b5480cc89a694f80c05d09fb3dfaa747fb1" }, "downloads": -1, "filename": "graphene_django_subscriptions-0.0.3.tar.gz", "has_sig": false, "md5_digest": "2917ce27abb86bbc6ce4d93f47366517", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 9323, "upload_time": "2018-01-05T23:02:57", "url": "https://files.pythonhosted.org/packages/27/a3/9dee6019dc42bbd79bfab8a21415fbe56b91d4d7b55b4561789faee957a4/graphene_django_subscriptions-0.0.3.tar.gz" } ], "0.0.4": [ { "comment_text": "", "digests": { "md5": "b6e6ecddad4cc6e96baaf3efb3cb656a", "sha256": "68672105d8f4966148fec89a01ba222de548bfa90ea43cdd6414b1c6fe2fce9a" }, "downloads": -1, "filename": "graphene_django_subscriptions-0.0.4-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "b6e6ecddad4cc6e96baaf3efb3cb656a", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 12245, "upload_time": "2018-01-18T14:14:54", "url": "https://files.pythonhosted.org/packages/78/ea/6181093348983113cfd3cd75db19118b27a4e8a309f257924b27d6dc2e94/graphene_django_subscriptions-0.0.4-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "810109552a5440f5ca6e1b3b680272b6", "sha256": "0fb2bdb6df0543df988b51a63572f73258c275a96af4411ad21702e69563830b" }, "downloads": -1, "filename": "graphene_django_subscriptions-0.0.4.zip", "has_sig": false, "md5_digest": "810109552a5440f5ca6e1b3b680272b6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 20390, "upload_time": "2018-01-18T14:15:04", "url": "https://files.pythonhosted.org/packages/6f/eb/fa3917e8ed9a0d6c6699d75bad8b8b843378bf94db1f3887dedbd6c287d0/graphene_django_subscriptions-0.0.4.zip" } ], "0.0.6": [ { "comment_text": "", "digests": { "md5": "95dd9f88d13c8064ebeb403376700a62", "sha256": "be3d7978efa03b7948065dc83c567e8690c4443fb6a8b6374440db089783db2c" }, "downloads": -1, "filename": "graphene_django_subscriptions-0.0.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "95dd9f88d13c8064ebeb403376700a62", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 9577, "upload_time": "2019-02-04T08:50:20", "url": "https://files.pythonhosted.org/packages/6f/4f/36cdcbb347536e397f0ed221c9f17aff7035c3eacc5dfbb24c88e1b23586/graphene_django_subscriptions-0.0.6-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4e1a3fe9748ede49f89d0f05bce58a08", "sha256": "4a50a487bad3410f49c9821e69e664dd3b73bb794b336137ba480806cfbcaae8" }, "downloads": -1, "filename": "graphene_django_subscriptions-0.0.6.tar.gz", "has_sig": false, "md5_digest": "4e1a3fe9748ede49f89d0f05bce58a08", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10235, "upload_time": "2019-02-04T08:50:22", "url": "https://files.pythonhosted.org/packages/32/20/f61dfd5ab7a1a6cec5424ecf4448449d9237b6376d18a8c125bb8788a787/graphene_django_subscriptions-0.0.6.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "95dd9f88d13c8064ebeb403376700a62", "sha256": "be3d7978efa03b7948065dc83c567e8690c4443fb6a8b6374440db089783db2c" }, "downloads": -1, "filename": "graphene_django_subscriptions-0.0.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "95dd9f88d13c8064ebeb403376700a62", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": null, "size": 9577, "upload_time": "2019-02-04T08:50:20", "url": "https://files.pythonhosted.org/packages/6f/4f/36cdcbb347536e397f0ed221c9f17aff7035c3eacc5dfbb24c88e1b23586/graphene_django_subscriptions-0.0.6-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4e1a3fe9748ede49f89d0f05bce58a08", "sha256": "4a50a487bad3410f49c9821e69e664dd3b73bb794b336137ba480806cfbcaae8" }, "downloads": -1, "filename": "graphene_django_subscriptions-0.0.6.tar.gz", "has_sig": false, "md5_digest": "4e1a3fe9748ede49f89d0f05bce58a08", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 10235, "upload_time": "2019-02-04T08:50:22", "url": "https://files.pythonhosted.org/packages/32/20/f61dfd5ab7a1a6cec5424ecf4448449d9237b6376d18a8c125bb8788a787/graphene_django_subscriptions-0.0.6.tar.gz" } ] }