Tutorial 2: request and response
From this point on, we will really begin to cover the core REST framework. Let us introduce a few basic building blocks.
Request Object
REST framework introduces a Request
target extended regular HttpRequest
, and more flexible request resolution. Request
The core function of the object is request.data
property, which is similar to request.POST
, but more useful for using the Web API.
request.POST # Only handles form data. Only works for 'POST' method.
request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods.
Response Object
REST framework also introduces an Response
object that TemplateResponse
uses content that is not presented and use content negotiation to determine the correct content type to be returned to the client.
return Response(data) # Renders to content type as requested by the client.
Status Codes
Using a digital HTTP status code in the view does not always show a significant readings, if the error code is an error, it is easy to notice. REST framework provides a more specific identifier for each status code, for example HTTP_400_BAD_REQUEST
in the status
module. It is always best to use these instead of using the numeric identifier.
View Package API
REST framework provides two packs may be used to write API view.
-
@api_view
For processing based on a function of decorator view. - The
APIView
view of the working class and class-based.
These packages provide a number of features, such as ensuring that Request
the receiving instance in view, and to Response
add to the context object may perform content negotiation.
Packaging also provides behavior, for example 405 Method Not Allowed
returns a response when appropriate, and processing a malformed input ParseError
any abnormality occurs during access request.data
.
put it together
Okay, let's go ahead and start using these new components to write some views.
We no longer need our JSONResponse
lesson views.py
, so delete it. Once completed, we can begin to reconstruct our views slightly.
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
@api_view(['GET', 'POST'])
def snippet_list(request):
"""
List all code snippets, or create a new snippet.
"""
if request.method == 'GET':
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = SnippetSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Our instance view is an improvement on the previous example. It is less verbose, and now we are using Forms API code is very similar. We also use named state code, which makes the response more obvious sense.
The following is a views.py
view of the module in a single code segment.
@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
"""
Retrieve, update or delete a code snippet.
"""
try:
snippet = Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = SnippetSerializer(snippet, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
snippet.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
This should be very familiar with - not much different from using conventional Django view.
Please note that we are no longer explicitly bind our request or response to a given content type. request.data
It can handle incoming json
requests, but it can also handle other formats. Similarly, we return the response object with data, but allows REST framework will be presented to us in response to the correct content type.
Add an optional format in our URL suffix
In order to respond with our not hardwired to a single content type of the fact that we added to the API format API endpoint suffix. Use the suffix format provides a clear reference to the URL given format, which means that we will be able to handle such an API for our http://example.com/api/items/4.json like URL.
First, format
add the keyword parameter in both views, as follows.
def snippet_list(request, format=None):
with
def snippet_detail(request, pk, format=None):
Now snippets/urls.py
little update file attached to format_suffix_patterns
a group other than the conventional URL.
from django.conf.urls import url
from snippets import views
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = [
path('snippets/', views.snippet_list),
path('snippets/<int:pk>', views.snippet_detail),
]
urlpatterns = format_suffix_patterns(urlpatterns)
We do not necessarily need to add these additional url mode, but it provides a simple, clean way for us to refer to a specific format.
Test API
Continue to test the command line API, as we Tutorial Part 1 had done. Although we sent an invalid request, but we have some better error handling method.
We can get a list of all the code segments as before.
http http://127.0.0.1:8000/snippets/
HTTP/1.1 200 OK
...
[
{
"id": 1,
"title": "",
"code": "foo = \"bar\"\n",
"linenos": false,
"language": "python",
"style": "friendly"
},
{
"id": 2,
"title": "",
"code": "print(\"hello, world\")\n",
"linenos": false,
"language": "python",
"style": "friendly"
}
]
We can use Accept
to control the format of the response headers we get:
http http://127.0.0.1:8000/snippets/ Accept:application/json # Request JSON
http http://127.0.0.1:8000/snippets/ Accept:text/html # Request HTML
Additional Format or by suffixes:
http http://127.0.0.1:8000/snippets.json # JSON suffix
http http://127.0.0.1:8000/snippets.api # Browsable API suffix
Similarly, we can use the Content-Type
header format of the control request from us.
# POST using form data
http --form POST http://127.0.0.1:8000/snippets/ code="print(123)"
{
"id": 3,
"title": "",
"code": "print(123)",
"linenos": false,
"language": "python",
"style": "friendly"
}
# POST using JSON
http --json POST http://127.0.0.1:8000/snippets/ code="print(456)"
{
"id": 4,
"title": "",
"code": "print(456)",
"linenos": false,
"language": "python",
"style": "friendly"
}
If you are --debug
in the http
add request a switch above, you will be able to see the type of request in the request header.
Now, by accessing http://127.0.0.1:8000/snippets/ , open API in a Web browser.
Reproduced in: https: //www.jianshu.com/p/c192740aa7c4