Pulling it all together

Okay, let's go ahead and start using these new components to refactor our views slightly.

  1. from rest_framework import status
  2. from rest_framework.decorators import api_view
  3. from rest_framework.response import Response
  4. from snippets.models import Snippet
  5. from snippets.serializers import SnippetSerializer
  6. @api_view(['GET', 'POST'])
  7. def snippet_list(request):
  8. """
  9. List all code snippets, or create a new snippet.
  10. """
  11. if request.method == 'GET':
  12. snippets = Snippet.objects.all()
  13. serializer = SnippetSerializer(snippets, many=True)
  14. return Response(serializer.data)
  15. elif request.method == 'POST':
  16. serializer = SnippetSerializer(data=request.data)
  17. if serializer.is_valid():
  18. serializer.save()
  19. return Response(serializer.data, status=status.HTTP_201_CREATED)
  20. return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Our instance view is an improvement over the previous example. It's a little more concise, and the code now feels very similar to if we were working with the Forms API. We're also using named status codes, which makes the response meanings more obvious.

Here is the view for an individual snippet, in the views.py module.

  1. @api_view(['GET', 'PUT', 'DELETE'])
  2. def snippet_detail(request, pk):
  3. """
  4. Retrieve, update or delete a code snippet.
  5. """
  6. try:
  7. snippet = Snippet.objects.get(pk=pk)
  8. except Snippet.DoesNotExist:
  9. return Response(status=status.HTTP_404_NOT_FOUND)
  10. if request.method == 'GET':
  11. serializer = SnippetSerializer(snippet)
  12. return Response(serializer.data)
  13. elif request.method == 'PUT':
  14. serializer = SnippetSerializer(snippet, data=request.data)
  15. if serializer.is_valid():
  16. serializer.save()
  17. return Response(serializer.data)
  18. return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  19. elif request.method == 'DELETE':
  20. snippet.delete()
  21. return Response(status=status.HTTP_204_NO_CONTENT)

This should all feel very familiar - it is not a lot different from working with regular Django views.

Notice that we're no longer explicitly tying our requests or responses to a given content type. request.data can handle incoming json requests, but it can also handle other formats. Similarly we're returning response objects with data, but allowing REST framework to render the response into the correct content type for us.