0
# AJAX and JSON Response Handling
1
2
Mixins for handling AJAX requests and generating JSON responses in Django class-based views. These mixins enable seamless integration between frontend JavaScript and Django backends through AJAX endpoints and structured JSON APIs.
3
4
## Capabilities
5
6
### JSON Response Generation
7
8
Basic JSON response functionality for API endpoints and AJAX responses.
9
10
```python { .api }
11
class JSONResponseMixin:
12
"""Basic serialized JSON responses"""
13
content_type = None
14
json_dumps_kwargs = None
15
json_encoder_class = None
16
17
def get_content_type(self):
18
"""Get appropriate content type for response"""
19
20
def get_json_dumps_kwargs(self):
21
"""Get kwargs for custom JSON compilation"""
22
23
def get_json_encoder_class(self):
24
"""Get encoder class to use"""
25
26
def render_json_response(self, context_dict, status=200):
27
"""Limited serialization for shipping plain data"""
28
29
def render_json_object_response(self, objects, **kwargs):
30
"""Serialize objects using Django's builtin JSON serializer"""
31
```
32
33
Usage example:
34
35
```python
36
from django.views.generic import ListView
37
from braces.views import JSONResponseMixin
38
39
class APIDataView(JSONResponseMixin, ListView):
40
model = MyModel
41
42
def get(self, request, *args, **kwargs):
43
queryset = self.get_queryset()
44
data = {
45
'results': list(queryset.values('id', 'name', 'created')),
46
'count': queryset.count()
47
}
48
return self.render_json_response(data)
49
50
# Custom JSON encoder for datetime fields
51
json_encoder_class = DjangoJSONEncoder
52
json_dumps_kwargs = {'indent': 2}
53
```
54
55
### AJAX Request Handling
56
57
Separate method handlers for AJAX vs regular HTTP requests.
58
59
```python { .api }
60
class AjaxResponseMixin:
61
"""Allows defining alternative methods for AJAX requests"""
62
63
def dispatch(self, request, *args, **kwargs):
64
"""Call appropriate handler method"""
65
66
def get_ajax(self, request, *args, **kwargs):
67
"""Handle GET request made with AJAX"""
68
69
def post_ajax(self, request, *args, **kwargs):
70
"""Handle POST request made with AJAX"""
71
72
def put_ajax(self, request, *args, **kwargs):
73
"""Handle PUT request made with AJAX"""
74
75
def delete_ajax(self, request, *args, **kwargs):
76
"""Handle DELETE request made with AJAX"""
77
```
78
79
Usage example:
80
81
```python
82
from django.views.generic import TemplateView
83
from braces.views import AjaxResponseMixin, JSONResponseMixin
84
85
class DualModeView(AjaxResponseMixin, JSONResponseMixin, TemplateView):
86
template_name = 'page.html'
87
88
def get(self, request, *args, **kwargs):
89
# Regular HTTP request - render template
90
return super().get(request, *args, **kwargs)
91
92
def get_ajax(self, request, *args, **kwargs):
93
# AJAX request - return JSON data
94
data = {'message': 'Hello from AJAX!'}
95
return self.render_json_response(data)
96
97
def post_ajax(self, request, *args, **kwargs):
98
# Handle AJAX form submissions
99
form_data = request.POST
100
# Process form...
101
return self.render_json_response({'status': 'success'})
102
```
103
104
### JSON Request Body Parsing
105
106
Parse and validate JSON request bodies with error handling.
107
108
```python { .api }
109
class JsonRequestResponseMixin(JSONResponseMixin):
110
"""Attempt to parse request body as JSON"""
111
require_json = False
112
error_response_dict = {'errors': ['Improperly formatted request']}
113
114
def render_bad_request_response(self, error_dict=None):
115
"""Generate errors for bad content"""
116
117
def get_request_json(self):
118
"""Get JSON included in the body"""
119
120
def dispatch(self, request, *args, **kwargs):
121
"""Trigger appropriate method"""
122
```
123
124
```python { .api }
125
class JSONRequestResponseMixin(JsonRequestResponseMixin):
126
"""Convenience alias for JsonRequestResponseMixin"""
127
```
128
129
Usage example:
130
131
```python
132
from django.views.generic import View
133
from braces.views import JsonRequestResponseMixin, CsrfExemptMixin
134
135
class APIEndpoint(CsrfExemptMixin, JsonRequestResponseMixin, View):
136
require_json = True # Return 400 for non-JSON requests
137
138
def post(self, request, *args, **kwargs):
139
# self.request_json contains parsed JSON data
140
if self.request_json is None:
141
return self.render_bad_request_response()
142
143
# Process JSON data
144
name = self.request_json.get('name')
145
email = self.request_json.get('email')
146
147
# Validate and save...
148
result = {'id': 123, 'status': 'created'}
149
return self.render_json_response(result, status=201)
150
151
def put(self, request, *args, **kwargs):
152
# Update existing record
153
record_id = kwargs.get('pk')
154
data = self.request_json
155
156
# Update logic...
157
return self.render_json_response({'status': 'updated'})
158
```
159
160
## Common Usage Patterns
161
162
### Building REST APIs
163
164
Combine mixins for full REST API functionality:
165
166
```python
167
from django.views.generic import View
168
from braces.views import CsrfExemptMixin, JsonRequestResponseMixin, AjaxResponseMixin
169
170
class RESTAPIView(CsrfExemptMixin, JsonRequestResponseMixin, AjaxResponseMixin, View):
171
require_json = True
172
173
def get(self, request, *args, **kwargs):
174
# Return JSON list or detail
175
return self.render_json_response({'data': []})
176
177
def post(self, request, *args, **kwargs):
178
# Create new resource from JSON
179
return self.render_json_response({'created': True}, status=201)
180
181
def put(self, request, *args, **kwargs):
182
# Update resource from JSON
183
return self.render_json_response({'updated': True})
184
185
def delete(self, request, *args, **kwargs):
186
# Delete resource
187
return self.render_json_response({'deleted': True}, status=204)
188
```
189
190
### Progressive Enhancement
191
192
Handle both regular page loads and AJAX requests:
193
194
```python
195
from django.views.generic import CreateView
196
from braces.views import AjaxResponseMixin, JSONResponseMixin
197
198
class ProgressiveFormView(AjaxResponseMixin, JSONResponseMixin, CreateView):
199
model = MyModel
200
template_name = 'form.html'
201
202
def form_valid(self, form):
203
# Save the object
204
response = super().form_valid(form)
205
return response
206
207
def form_valid_ajax(self, form):
208
# AJAX version - return JSON instead of redirect
209
self.object = form.save()
210
return self.render_json_response({
211
'success': True,
212
'id': self.object.pk,
213
'url': self.object.get_absolute_url()
214
})
215
216
def form_invalid_ajax(self, form):
217
# Return form errors as JSON
218
return self.render_json_response({
219
'success': False,
220
'errors': form.errors
221
}, status=400)
222
```
223
224
### Custom JSON Serialization
225
226
Handle complex data types with custom encoders:
227
228
```python
229
import json
230
from decimal import Decimal
231
from datetime import datetime
232
from django.core.serializers.json import DjangoJSONEncoder
233
from braces.views import JSONResponseMixin
234
235
class CustomJSONEncoder(DjangoJSONEncoder):
236
def default(self, obj):
237
if isinstance(obj, Decimal):
238
return float(obj)
239
return super().default(obj)
240
241
class CustomJSONView(JSONResponseMixin, View):
242
json_encoder_class = CustomJSONEncoder
243
json_dumps_kwargs = {'indent': 2, 'sort_keys': True}
244
245
def get(self, request):
246
data = {
247
'timestamp': datetime.now(),
248
'price': Decimal('29.99'),
249
'items': ['item1', 'item2']
250
}
251
return self.render_json_response(data)
252
```