or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

access-control.mdajax-json.mdform-processing.mdhttp-utilities.mdindex.mdquery-optimization.md

ajax-json.mddocs/

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

```