0
# Django Views
1
2
Django view classes for serving GraphQL endpoints with configurable GraphiQL interface, middleware support, and comprehensive HTTP request handling. These views provide the bridge between Django's HTTP layer and GraphQL execution.
3
4
## Capabilities
5
6
### GraphQLView
7
8
Django view for serving GraphQL endpoints with built-in GraphiQL support, middleware integration, and flexible configuration options.
9
10
```python { .api }
11
class GraphQLView(django.views.generic.View):
12
"""
13
Django view for serving GraphQL endpoint with GraphiQL support.
14
15
Handles GET requests for GraphiQL interface and POST requests for
16
GraphQL query execution with comprehensive error handling and
17
middleware integration.
18
"""
19
20
schema = None # GraphQL schema
21
executor = None # Custom executor
22
middleware = None # GraphQL middleware
23
graphiql = False # Enable GraphiQL interface
24
pretty = False # Pretty print JSON responses
25
batch = False # Enable query batching
26
27
def __init__(self, schema=None, executor=None, middleware=None,
28
graphiql=False, pretty=False, batch=False, **kwargs):
29
"""
30
Initialize GraphQL view.
31
32
Parameters:
33
- schema: GraphQL schema instance
34
- executor: Custom GraphQL executor
35
- middleware: List of GraphQL middleware
36
- graphiql: Enable GraphiQL development interface
37
- pretty: Pretty print JSON responses
38
- batch: Enable batched query execution
39
- **kwargs: Additional view options
40
"""
41
42
def dispatch(self, request, *args, **kwargs):
43
"""
44
Handle HTTP requests and route to appropriate methods.
45
46
Parameters:
47
- request: Django HTTP request
48
- *args: URL arguments
49
- **kwargs: URL keyword arguments
50
51
Returns:
52
django.http.HttpResponse: HTTP response
53
"""
54
55
def get_response(self, request, data, show_graphiql=False):
56
"""
57
Process GraphQL requests and return responses.
58
59
Parameters:
60
- request: Django HTTP request
61
- data: GraphQL query data
62
- show_graphiql: Whether to show GraphiQL interface
63
64
Returns:
65
django.http.HttpResponse: GraphQL response
66
"""
67
68
def render_graphiql(self, request, **data):
69
"""
70
Render GraphiQL development interface.
71
72
Parameters:
73
- request: Django HTTP request
74
- **data: GraphiQL configuration data
75
76
Returns:
77
django.http.HttpResponse: GraphiQL HTML response
78
"""
79
80
def get_graphql_params(self, request, data):
81
"""
82
Extract GraphQL parameters from request.
83
84
Parameters:
85
- request: Django HTTP request
86
- data: Request data
87
88
Returns:
89
dict: GraphQL execution parameters (query, variables, operation_name)
90
"""
91
92
def format_error(self, error):
93
"""
94
Format GraphQL execution errors.
95
96
Parameters:
97
- error: GraphQL execution error
98
99
Returns:
100
dict: Formatted error data
101
"""
102
103
def get_context(self, request):
104
"""
105
Get GraphQL execution context from request.
106
107
Parameters:
108
- request: Django HTTP request
109
110
Returns:
111
dict: Execution context
112
"""
113
114
def can_display_graphiql(self, request, data):
115
"""
116
Determine if GraphiQL interface should be displayed.
117
118
Parameters:
119
- request: Django HTTP request
120
- data: Request data
121
122
Returns:
123
bool: True if GraphiQL should be shown
124
"""
125
126
@classmethod
127
def as_view(cls, **initkwargs):
128
"""
129
Create view instance with configuration.
130
131
Parameters:
132
- **initkwargs: View initialization arguments
133
134
Returns:
135
function: Configured view function
136
"""
137
```
138
139
### HttpError
140
141
HTTP-specific exception for GraphQL errors with response status code control and custom error messaging.
142
143
```python { .api }
144
class HttpError(Exception):
145
"""
146
HTTP-specific exception for GraphQL errors.
147
148
Allows GraphQL resolvers to return specific HTTP status codes
149
and custom error responses for client error handling.
150
"""
151
152
def __init__(self, response, message=None, *args, **kwargs):
153
"""
154
Initialize HTTP error.
155
156
Parameters:
157
- response: django.http.HttpResponse or status code
158
- message: Error message
159
- *args: Additional exception arguments
160
- **kwargs: Additional exception keyword arguments
161
"""
162
self.response = response
163
self.message = message
164
super().__init__(message, *args, **kwargs)
165
```
166
167
## Usage Examples
168
169
### Basic GraphQL Endpoint
170
171
```python
172
from django.urls import path
173
from graphene_django.views import GraphQLView
174
from myapp.schema import schema
175
176
urlpatterns = [
177
path('graphql/', GraphQLView.as_view(schema=schema)),
178
]
179
```
180
181
### GraphQL with GraphiQL Development Interface
182
183
```python
184
from django.conf import settings
185
186
urlpatterns = [
187
path('graphql/', GraphQLView.as_view(
188
schema=schema,
189
graphiql=settings.DEBUG # Enable GraphiQL in development
190
)),
191
]
192
```
193
194
### Custom View with Middleware
195
196
```python
197
from graphene_django.debug import DjangoDebugMiddleware
198
199
class CustomGraphQLView(GraphQLView):
200
def get_context(self, request):
201
return {
202
'request': request,
203
'user': request.user,
204
}
205
206
urlpatterns = [
207
path('graphql/', CustomGraphQLView.as_view(
208
schema=schema,
209
middleware=[DjangoDebugMiddleware()],
210
graphiql=True
211
)),
212
]
213
```
214
215
### Authentication-Protected Endpoint
216
217
```python
218
from django.contrib.auth.decorators import login_required
219
from django.utils.decorators import method_decorator
220
221
@method_decorator(login_required, name='dispatch')
222
class ProtectedGraphQLView(GraphQLView):
223
pass
224
225
urlpatterns = [
226
path('api/graphql/', ProtectedGraphQLView.as_view(schema=schema)),
227
]
228
```
229
230
### Custom Error Handling
231
232
```python
233
import json
234
from django.http import JsonResponse
235
236
class CustomGraphQLView(GraphQLView):
237
def format_error(self, error):
238
formatted_error = super().format_error(error)
239
240
# Add custom error logging
241
if hasattr(error, 'original_error'):
242
logger.error(f"GraphQL Error: {error.original_error}")
243
244
return formatted_error
245
246
def get_response(self, request, data, show_graphiql=False):
247
try:
248
return super().get_response(request, data, show_graphiql)
249
except Exception as e:
250
return JsonResponse({
251
'errors': [{'message': 'Internal server error'}]
252
}, status=500)
253
```
254
255
### Batched Queries Support
256
257
```python
258
urlpatterns = [
259
path('graphql/', GraphQLView.as_view(
260
schema=schema,
261
batch=True, # Enable query batching
262
graphiql=True
263
)),
264
]
265
266
# Client can send multiple queries:
267
# POST /graphql/
268
# [
269
# {"query": "query { users { id } }"},
270
# {"query": "query { posts { title } }"}
271
# ]
272
```
273
274
### Custom Executor Integration
275
276
```python
277
from graphql import GraphQLError
278
from concurrent.futures import ThreadPoolExecutor
279
280
def custom_executor(fn, *args, **kwargs):
281
"""Custom executor with thread pool."""
282
with ThreadPoolExecutor(max_workers=4) as executor:
283
return executor.submit(fn, *args, **kwargs).result()
284
285
urlpatterns = [
286
path('graphql/', GraphQLView.as_view(
287
schema=schema,
288
executor=custom_executor
289
)),
290
]
291
```
292
293
### CORS Configuration
294
295
```python
296
from django.views.decorators.csrf import csrf_exempt
297
from django.utils.decorators import method_decorator
298
299
@method_decorator(csrf_exempt, name='dispatch')
300
class CORSGraphQLView(GraphQLView):
301
def dispatch(self, request, *args, **kwargs):
302
response = super().dispatch(request, *args, **kwargs)
303
response['Access-Control-Allow-Origin'] = '*'
304
response['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
305
response['Access-Control-Allow-Headers'] = 'Content-Type, Authorization'
306
return response
307
```
308
309
### HTTP Error Usage in Resolvers
310
311
```python
312
from graphene_django.views import HttpError
313
from django.http import HttpResponseForbidden
314
315
class Query(graphene.ObjectType):
316
sensitive_data = graphene.String()
317
318
def resolve_sensitive_data(self, info):
319
if not info.context.user.is_staff:
320
raise HttpError(
321
HttpResponseForbidden("Access denied"),
322
message="Insufficient permissions"
323
)
324
return "Secret information"
325
```