0
# Views and ViewSets
1
2
Class-based views and ViewSets for handling HTTP requests in Django REST Framework. Provides everything from basic APIView for custom logic to full CRUD ViewSets with automatic URL routing.
3
4
## Capabilities
5
6
### Base API View
7
8
Foundation view class providing core DRF functionality including authentication, permissions, content negotiation, and exception handling.
9
10
```python { .api }
11
class APIView(View):
12
"""
13
Base class for all DRF views providing core API functionality.
14
"""
15
# Class attributes for configuration
16
authentication_classes = [] # List of authentication classes
17
permission_classes = [] # List of permission classes
18
parser_classes = [] # List of parser classes
19
renderer_classes = [] # List of renderer classes
20
throttle_classes = [] # List of throttle classes
21
content_negotiation_class = None # Content negotiation class
22
23
def dispatch(self, request, *args, **kwargs):
24
"""
25
Main entry point for handling requests.
26
27
Args:
28
request: Django request object (enhanced to DRF Request)
29
*args: URL arguments
30
**kwargs: URL keyword arguments
31
32
Returns:
33
Response: DRF Response object
34
"""
35
36
def initial(self, request, *args, **kwargs):
37
"""
38
Perform authentication, permissions, and throttling checks.
39
"""
40
41
def handle_exception(self, exc):
42
"""
43
Handle any exception that occurs during request processing.
44
45
Args:
46
exc: Exception that occurred
47
48
Returns:
49
Response: Error response
50
"""
51
52
def get_permissions(self):
53
"""
54
Instantiate and return permission classes for this view.
55
56
Returns:
57
list: Permission class instances
58
"""
59
60
def get_authenticators(self):
61
"""
62
Instantiate and return authentication classes for this view.
63
64
Returns:
65
list: Authentication class instances
66
"""
67
68
def get_parsers(self):
69
"""
70
Instantiate and return parser classes for this view.
71
72
Returns:
73
list: Parser class instances
74
"""
75
76
def get_renderers(self):
77
"""
78
Instantiate and return renderer classes for this view.
79
80
Returns:
81
list: Renderer class instances
82
"""
83
```
84
85
### Generic API View
86
87
Base class for generic views providing common functionality like queryset handling, serializer management, and pagination.
88
89
```python { .api }
90
class GenericAPIView(APIView):
91
"""
92
Base class for generic views with queryset and serializer support.
93
"""
94
queryset = None # Base queryset for the view
95
serializer_class = None # Serializer class to use
96
lookup_field = 'pk' # Field for object lookup
97
lookup_url_kwarg = None # URL kwarg for lookup
98
filter_backends = [] # List of filter backend classes
99
pagination_class = None # Pagination class
100
101
def get_queryset(self):
102
"""
103
Get the queryset for this view.
104
105
Returns:
106
QuerySet: Filtered queryset
107
"""
108
109
def get_object(self):
110
"""
111
Get single object based on lookup parameters.
112
113
Returns:
114
Model instance
115
116
Raises:
117
Http404: If object not found
118
"""
119
120
def get_serializer(self, *args, **kwargs):
121
"""
122
Get serializer instance with current context.
123
124
Returns:
125
Serializer: Configured serializer instance
126
"""
127
128
def get_serializer_class(self):
129
"""
130
Get serializer class for this view.
131
132
Returns:
133
Serializer class
134
"""
135
136
def get_serializer_context(self):
137
"""
138
Get context data for serializer.
139
140
Returns:
141
dict: Context dictionary
142
"""
143
144
def paginate_queryset(self, queryset):
145
"""
146
Paginate queryset if pagination is configured.
147
148
Args:
149
queryset: QuerySet to paginate
150
151
Returns:
152
list or None: Paginated results
153
"""
154
155
def get_paginated_response(self, data):
156
"""
157
Get paginated response for data.
158
159
Args:
160
data: Serialized data
161
162
Returns:
163
Response: Paginated response
164
"""
165
166
def filter_queryset(self, queryset):
167
"""
168
Apply filtering backends to queryset.
169
170
Args:
171
queryset: Base queryset
172
173
Returns:
174
QuerySet: Filtered queryset
175
"""
176
```
177
178
### Concrete Generic Views
179
180
Pre-built views for common API patterns providing standard CRUD operations.
181
182
```python { .api }
183
class CreateAPIView(GenericAPIView):
184
"""Handle POST requests to create new objects."""
185
def post(self, request, *args, **kwargs): ...
186
187
class ListAPIView(GenericAPIView):
188
"""Handle GET requests to list objects."""
189
def get(self, request, *args, **kwargs): ...
190
191
class RetrieveAPIView(GenericAPIView):
192
"""Handle GET requests to retrieve single object."""
193
def get(self, request, *args, **kwargs): ...
194
195
class DestroyAPIView(GenericAPIView):
196
"""Handle DELETE requests to delete objects."""
197
def delete(self, request, *args, **kwargs): ...
198
199
class UpdateAPIView(GenericAPIView):
200
"""Handle PUT/PATCH requests to update objects."""
201
def put(self, request, *args, **kwargs): ...
202
def patch(self, request, *args, **kwargs): ...
203
204
# Combined views
205
class ListCreateAPIView(GenericAPIView):
206
"""Handle GET (list) and POST (create) requests."""
207
def get(self, request, *args, **kwargs): ...
208
def post(self, request, *args, **kwargs): ...
209
210
class RetrieveUpdateAPIView(GenericAPIView):
211
"""Handle GET (retrieve) and PUT/PATCH (update) requests."""
212
def get(self, request, *args, **kwargs): ...
213
def put(self, request, *args, **kwargs): ...
214
def patch(self, request, *args, **kwargs): ...
215
216
class RetrieveDestroyAPIView(GenericAPIView):
217
"""Handle GET (retrieve) and DELETE (destroy) requests."""
218
def get(self, request, *args, **kwargs): ...
219
def delete(self, request, *args, **kwargs): ...
220
221
class RetrieveUpdateDestroyAPIView(GenericAPIView):
222
"""Handle GET (retrieve), PUT/PATCH (update), and DELETE (destroy)."""
223
def get(self, request, *args, **kwargs): ...
224
def put(self, request, *args, **kwargs): ...
225
def patch(self, request, *args, **kwargs): ...
226
def delete(self, request, *args, **kwargs): ...
227
```
228
229
### ViewSets
230
231
ViewSet classes that group related view logic and can generate URL patterns automatically.
232
233
```python { .api }
234
class ViewSet(ViewSetMixin, APIView):
235
"""
236
Basic ViewSet class providing action-based routing.
237
"""
238
def list(self, request):
239
"""Handle GET requests to list objects."""
240
241
def create(self, request):
242
"""Handle POST requests to create objects."""
243
244
def retrieve(self, request, pk=None):
245
"""Handle GET requests to retrieve single object."""
246
247
def update(self, request, pk=None):
248
"""Handle PUT requests to update objects."""
249
250
def partial_update(self, request, pk=None):
251
"""Handle PATCH requests to partially update objects."""
252
253
def destroy(self, request, pk=None):
254
"""Handle DELETE requests to destroy objects."""
255
256
class GenericViewSet(ViewSetMixin, GenericAPIView):
257
"""
258
Generic ViewSet with queryset and serializer support.
259
"""
260
261
class ReadOnlyModelViewSet(GenericViewSet):
262
"""
263
ViewSet providing read-only operations (list and retrieve).
264
"""
265
def list(self, request, *args, **kwargs): ...
266
def retrieve(self, request, *args, **kwargs): ...
267
268
class ModelViewSet(GenericViewSet):
269
"""
270
Full CRUD ViewSet with all standard operations.
271
"""
272
def list(self, request, *args, **kwargs): ...
273
def create(self, request, *args, **kwargs): ...
274
def retrieve(self, request, *args, **kwargs): ...
275
def update(self, request, *args, **kwargs): ...
276
def partial_update(self, request, *args, **kwargs): ...
277
def destroy(self, request, *args, **kwargs): ...
278
```
279
280
### View Mixins
281
282
Modular functionality that can be mixed into views for specific behaviors.
283
284
```python { .api }
285
class CreateModelMixin:
286
"""Provide create functionality for views."""
287
def create(self, request, *args, **kwargs):
288
"""
289
Create new model instance.
290
291
Returns:
292
Response: 201 Created with serialized data
293
"""
294
295
def perform_create(self, serializer):
296
"""Save the object during creation."""
297
serializer.save()
298
299
def get_success_headers(self, data):
300
"""Get headers for successful creation response."""
301
302
class ListModelMixin:
303
"""Provide list functionality for views."""
304
def list(self, request, *args, **kwargs):
305
"""
306
List model instances with pagination and filtering.
307
308
Returns:
309
Response: 200 OK with serialized data list
310
"""
311
312
class RetrieveModelMixin:
313
"""Provide retrieve functionality for views."""
314
def retrieve(self, request, *args, **kwargs):
315
"""
316
Retrieve single model instance.
317
318
Returns:
319
Response: 200 OK with serialized data
320
"""
321
322
class UpdateModelMixin:
323
"""Provide update functionality for views."""
324
def update(self, request, *args, **kwargs):
325
"""
326
Update model instance (full update).
327
328
Returns:
329
Response: 200 OK with serialized data
330
"""
331
332
def partial_update(self, request, *args, **kwargs):
333
"""
334
Partially update model instance.
335
336
Returns:
337
Response: 200 OK with serialized data
338
"""
339
340
def perform_update(self, serializer):
341
"""Save the object during update."""
342
serializer.save()
343
344
class DestroyModelMixin:
345
"""Provide destroy functionality for views."""
346
def destroy(self, request, *args, **kwargs):
347
"""
348
Delete model instance.
349
350
Returns:
351
Response: 204 No Content
352
"""
353
354
def perform_destroy(self, instance):
355
"""Delete the object."""
356
instance.delete()
357
```
358
359
## Usage Examples
360
361
### Function-Based View
362
363
```python
364
from rest_framework.decorators import api_view, permission_classes
365
from rest_framework.permissions import IsAuthenticated
366
from rest_framework.response import Response
367
from rest_framework import status
368
369
@api_view(['GET', 'POST'])
370
@permission_classes([IsAuthenticated])
371
def book_list(request):
372
if request.method == 'GET':
373
books = Book.objects.all()
374
serializer = BookSerializer(books, many=True)
375
return Response(serializer.data)
376
377
elif request.method == 'POST':
378
serializer = BookSerializer(data=request.data)
379
if serializer.is_valid():
380
serializer.save()
381
return Response(serializer.data, status=status.HTTP_201_CREATED)
382
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
383
```
384
385
### Class-Based APIView
386
387
```python
388
from rest_framework.views import APIView
389
from rest_framework.response import Response
390
from rest_framework.permissions import IsAuthenticated
391
392
class BookListView(APIView):
393
permission_classes = [IsAuthenticated]
394
395
def get(self, request):
396
books = Book.objects.all()
397
serializer = BookSerializer(books, many=True)
398
return Response(serializer.data)
399
400
def post(self, request):
401
serializer = BookSerializer(data=request.data)
402
if serializer.is_valid():
403
serializer.save()
404
return Response(serializer.data, status=status.HTTP_201_CREATED)
405
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
406
```
407
408
### Generic Views
409
410
```python
411
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView
412
from rest_framework.permissions import IsAuthenticatedOrReadOnly
413
414
class BookListCreateView(ListCreateAPIView):
415
queryset = Book.objects.all()
416
serializer_class = BookSerializer
417
permission_classes = [IsAuthenticatedOrReadOnly]
418
419
def perform_create(self, serializer):
420
serializer.save(owner=self.request.user)
421
422
class BookDetailView(RetrieveUpdateDestroyAPIView):
423
queryset = Book.objects.all()
424
serializer_class = BookSerializer
425
permission_classes = [IsAuthenticatedOrReadOnly]
426
```
427
428
### ViewSets with Custom Actions
429
430
```python
431
from rest_framework.viewsets import ModelViewSet
432
from rest_framework.decorators import action
433
from rest_framework.response import Response
434
435
class BookViewSet(ModelViewSet):
436
queryset = Book.objects.all()
437
serializer_class = BookSerializer
438
permission_classes = [IsAuthenticatedOrReadOnly]
439
440
@action(detail=True, methods=['post'])
441
def set_favorite(self, request, pk=None):
442
book = self.get_object()
443
# Custom logic for favoriting
444
return Response({'status': 'favorite set'})
445
446
@action(detail=False, methods=['get'])
447
def recent_books(self, request):
448
recent = Book.objects.filter(created__gte=timezone.now() - timedelta(days=7))
449
serializer = self.get_serializer(recent, many=True)
450
return Response(serializer.data)
451
```
452
453
## Utility Functions
454
455
```python { .api }
456
def get_view_name(view):
457
"""
458
Get textual name for view class.
459
460
Args:
461
view: View class or instance
462
463
Returns:
464
str: Human-readable view name
465
"""
466
467
def get_view_description(view, html=False):
468
"""
469
Get description for view from docstring.
470
471
Args:
472
view: View class or instance
473
html (bool): Return HTML formatted description
474
475
Returns:
476
str: View description text
477
"""
478
479
def exception_handler(exc, context):
480
"""
481
Default exception handler for DRF views.
482
483
Args:
484
exc: Exception that occurred
485
context (dict): Context information
486
487
Returns:
488
Response or None: Error response or None to use default
489
"""
490
```