1
+ ==========
1
2
GraphQL WS
2
3
==========
3
4
4
- Websocket server for GraphQL subscriptions.
5
+ Websocket backend for GraphQL subscriptions.
6
+
7
+ Supports the following application servers:
8
+
9
+ Python 3 application servers, using asyncio:
10
+
11
+ * `aiohttp `_
12
+ * `websockets compatible servers `_ such as Sanic
13
+ (via `websockets <https://github.com/aaugustin/websockets/ >`__ library)
14
+ * `Django v2+ `_
5
15
6
- Currently supports:
16
+ Python 2 application servers:
17
+
18
+ * `Gevent compatible servers `_ such as Flask
19
+ * `Django v1.x `_
20
+ (via `channels v1.x <https://channels.readthedocs.io/en/1.x/inshort.html >`__)
7
21
8
- * `aiohttp <https://github.com/graphql-python/graphql-ws#aiohttp >`__
9
- * `Gevent <https://github.com/graphql-python/graphql-ws#gevent >`__
10
- * Sanic (uses `websockets <https://github.com/aaugustin/websockets/ >`__
11
- library)
12
22
13
23
Installation instructions
14
24
=========================
@@ -19,21 +29,54 @@ For instaling graphql-ws, just run this command in your shell
19
29
20
30
pip install graphql-ws
21
31
32
+
22
33
Examples
23
- --------
34
+ ========
35
+
36
+ Python 3 servers
37
+ ----------------
38
+
39
+ Create a subscribable schema like this:
40
+
41
+ .. code :: python
42
+
43
+ import asyncio
44
+ import graphene
45
+
46
+
47
+ class Query (graphene .ObjectType ):
48
+ hello = graphene.String()
49
+
50
+ @ staticmethod
51
+ def resolve_hello (obj , info , ** kwargs ):
52
+ return " world"
53
+
54
+
55
+ class Subscription (graphene .ObjectType ):
56
+ count_seconds = graphene.Float(up_to = graphene.Int())
57
+
58
+ async def resolve_count_seconds (root , info , up_to ):
59
+ for i in range (up_to):
60
+ yield i
61
+ await asyncio.sleep(1 .)
62
+ yield up_to
63
+
64
+
65
+ schema = graphene.Schema(query = Query, subscription = Subscription)
24
66
25
67
aiohttp
26
68
~~~~~~~
27
69
28
- For setting up, just plug into your aiohttp server.
70
+ Then just plug into your aiohttp server.
29
71
30
72
.. code :: python
31
73
32
74
from graphql_ws.aiohttp import AiohttpSubscriptionServer
33
-
75
+ from .schema import schema
34
76
35
77
subscription_server = AiohttpSubscriptionServer(schema)
36
78
79
+
37
80
async def subscriptions (request ):
38
81
ws = web.WebSocketResponse(protocols = (' graphql-ws' ,))
39
82
await ws.prepare(request)
@@ -47,16 +90,20 @@ For setting up, just plug into your aiohttp server.
47
90
48
91
web.run_app(app, port = 8000 )
49
92
50
- Sanic
51
- ~~~~~
93
+ You can see a full example here:
94
+ https://github.com/graphql-python/graphql-ws/tree/master/examples/aiohttp
95
+
96
+
97
+ websockets compatible servers
98
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
52
99
53
- Works with any framework that uses the websockets library for it’s
54
- websocket implementation. For this example, plug in your Sanic server.
100
+ Works with any framework that uses the websockets library for its websocket
101
+ implementation. For this example, plug in your Sanic server.
55
102
56
103
.. code :: python
57
104
58
105
from graphql_ws.websockets_lib import WsLibSubscriptionServer
59
-
106
+ from . import schema
60
107
61
108
app = Sanic(__name__ )
62
109
@@ -70,49 +117,61 @@ websocket implementation. For this example, plug in your Sanic server.
70
117
71
118
app.run(host = " 0.0.0.0" , port = 8000 )
72
119
73
- And then, plug into a subscribable schema:
74
120
75
- .. code :: python
121
+ Django v2+
122
+ ~~~~~~~~~~
76
123
77
- import asyncio
78
- import graphene
79
124
125
+ Django Channels 2
126
+ ~~~~~~~~~~~~~~~~~
80
127
81
- class Query (graphene .ObjectType ):
82
- base = graphene.String()
128
+ Set up with Django Channels just takes three steps:
83
129
130
+ 1. Install the apps
131
+ 2. Set up your schema
132
+ 3. Configure the channels router application
84
133
85
- class Subscription (graphene .ObjectType ):
86
- count_seconds = graphene.Float(up_to = graphene.Int())
134
+ First ``pip install channels `` and it to your ``INSTALLED_APPS ``. If you
135
+ want graphiQL, install the ``graphql_ws.django `` app before
136
+ ``graphene_django `` to serve a graphiQL template that will work with
137
+ websockets:
87
138
88
- async def resolve_count_seconds (root , info , up_to ):
89
- for i in range (up_to):
90
- yield i
91
- await asyncio.sleep(1 .)
92
- yield up_to
139
+ .. code :: python
93
140
141
+ INSTALLED_APPS = [
142
+ " channels" ,
143
+ " graphql_ws.django" ,
144
+ " graphene_django" ,
145
+ # ...
146
+ ]
94
147
95
- schema = graphene.Schema( query = Query, subscription = Subscription)
148
+ Point to your schema in Django settings:
96
149
97
- You can see a full example here:
98
- https://github.com/graphql-python/graphql-ws/tree/master/examples/aiohttp
150
+ .. code :: python
99
151
100
- Gevent
101
- ~~~~~~
152
+ GRAPHENE = {
153
+ ' SCHEMA' : ' yourproject.schema.schema'
154
+ }
102
155
103
- For setting up, just plug into your Gevent server.
156
+ Finally, you can set up channels routing yourself (maybe using
157
+ ``graphql_ws.django.routing.websocket_urlpatterns `` in your
158
+ ``URLRouter ``), or you can just use one of the preset channels
159
+ applications:
104
160
105
161
.. code :: python
106
162
107
- subscription_server = GeventSubscriptionServer(schema)
108
- app.app_protocol = lambda environ_path_info : ' graphql-ws'
163
+ ASGI_APPLICATION = ' graphql_ws.django.routing.application'
164
+ # or
165
+ ASGI_APPLICATION = ' graphql_ws.django.routing.auth_application'
109
166
110
- @sockets.route (' /subscriptions' )
111
- def echo_socket (ws ):
112
- subscription_server.handle(ws)
113
- return []
167
+ Run ``./manage.py runserver `` and go to
168
+ `http://localhost:8000/graphql `__ to test!
114
169
115
- And then, plug into a subscribable schema:
170
+
171
+ Python 2 servers
172
+ -----------------
173
+
174
+ Create a subscribable schema like this:
116
175
117
176
.. code :: python
118
177
@@ -121,7 +180,11 @@ And then, plug into a subscribable schema:
121
180
122
181
123
182
class Query (graphene .ObjectType ):
124
- base = graphene.String()
183
+ hello = graphene.String()
184
+
185
+ @ staticmethod
186
+ def resolve_hello (obj , info , ** kwargs ):
187
+ return " world"
125
188
126
189
127
190
class Subscription (graphene .ObjectType ):
@@ -135,71 +198,54 @@ And then, plug into a subscribable schema:
135
198
136
199
schema = graphene.Schema(query = Query, subscription = Subscription)
137
200
138
- You can see a full example here:
139
- https://github.com/graphql-python/graphql-ws/tree/master/examples/flask_gevent
140
-
141
- Django Channels
142
- ~~~~~~~~~~~~~~~
201
+ Gevent compatible servers
202
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
143
203
144
- First ``pip install channels `` and it to your django apps
145
-
146
- Then add the following to your settings.py
204
+ Then just plug into your Gevent server, for example, Flask:
147
205
148
206
.. code :: python
149
207
150
- CHANNELS_WS_PROTOCOLS = [" graphql-ws" , ]
151
- CHANNEL_LAYERS = {
152
- " default" : {
153
- " BACKEND" : " asgiref.inmemory.ChannelLayer" ,
154
- " ROUTING" : " django_subscriptions.urls.channel_routing" ,
155
- },
156
-
157
- }
158
-
159
- Setup your graphql schema
208
+ from flask_sockets import Sockets
209
+ from graphql_ws.gevent import GeventSubscriptionServer
210
+ from schema import schema
160
211
161
- .. code :: python
162
-
163
- import graphene
164
- from rx import Observable
165
-
166
-
167
- class Query (graphene .ObjectType ):
168
- hello = graphene.String()
212
+ subscription_server = GeventSubscriptionServer(schema)
213
+ app.app_protocol = lambda environ_path_info : ' graphql-ws'
169
214
170
- def resolve_hello (self , info , ** kwargs ):
171
- return ' world'
172
215
173
- class Subscription (graphene .ObjectType ):
216
+ @sockets.route (' /subscriptions' )
217
+ def echo_socket (ws ):
218
+ subscription_server.handle(ws)
219
+ return []
174
220
175
- count_seconds = graphene.Int(up_to = graphene.Int())
221
+ You can see a full example here:
222
+ https://github.com/graphql-python/graphql-ws/tree/master/examples/flask_gevent
176
223
224
+ Django v1.x
225
+ ~~~~~~~~~~~
177
226
178
- def resolve_count_seconds (
179
- root ,
180
- info ,
181
- up_to = 5
182
- ):
183
- return Observable.interval(1000 )\
184
- .map(lambda i : " {0} " .format(i))\
185
- .take_while(lambda i : int (i) <= up_to)
186
-
227
+ For Django v1.x and Django Channels v1.x, setup your schema in ``settings.py ``
187
228
229
+ .. code :: python
188
230
189
- schema = graphene.Schema(
190
- query = Query,
191
- subscription = Subscription
192
- )
231
+ GRAPHENE = {
232
+ ' SCHEMA' : ' yourproject.schema.schema'
233
+ }
193
234
194
- Setup your schema in settings.py
235
+ Then ``pip install "channels<1" `` and it to your django apps, adding the
236
+ following to your ``settings.py ``
195
237
196
238
.. code :: python
197
239
198
- GRAPHENE = {
199
- ' SCHEMA' : ' path.to.schema'
240
+ CHANNELS_WS_PROTOCOLS = [" graphql-ws" , ]
241
+ CHANNEL_LAYERS = {
242
+ " default" : {
243
+ " BACKEND" : " asgiref.inmemory.ChannelLayer" ,
244
+ " ROUTING" : " django_subscriptions.urls.channel_routing" ,
245
+ },
200
246
}
201
247
202
- and finally add the channel routes
248
+ And finally add the channel routes
203
249
204
250
.. code :: python
205
251
@@ -209,3 +255,6 @@ and finally add the channel routes
209
255
channel_routing = [
210
256
route_class(GraphQLSubscriptionConsumer, path = r " ^ /subscriptions" ),
211
257
]
258
+
259
+ You can see a full example here:
260
+ https://github.com/graphql-python/graphql-ws/tree/master/examples/django_subscriptions
0 commit comments