Django rest framework requests and responses (detailed description), djangoframework
In the previous article, the specified data is returned when a specified URL is accessed, which also reflects the RESTful API concept. Each URL represents a resource. Of course, we also know that another feature of RESTful APIS is that different request actions will return different responses, this article describes the convenient operations that the django-rest-framework tool brings to us.
1. Request object
When writing Django view functions, we usually include a request parameter, which can handle the regular HttpRequest sent by browsers when accessing webpages during website construction. But now we have imported django-rest-framework, which can expand the request and provide more flexible request Parsing. What is this feature reflected in? See the following example:
<SPAN style = "FONT-SIZE: 13px"> request. POST # Only handles <SPAN style = "COLOR: # ff0000"> form data </SPAN>. only works for '<SPAN style = "COLOR: # ff0000"> POST </SPAN>' method. request. data # Handles <SPAN style = "COLOR: # ff0000"> arbitrary (any) data </SPAN>. works for '<SPAN style = "COLOR: # ff0000"> Post', 'put' and 'patch </SPAN>' methods. </SPAN>
Request. POST can only process POST requests initiated by the front end and only data submitted by forms. Request. data can process arbitrary data, not just form data submitted by the front end, but can be used for post, put, and patch requests.
Ii. Response object
Like the request object, django-rest-framework has also made a very practical expansion. In my previous article, snippets/views. in py, We have imported JsonResponse for returning responses in json format, which is like this in the view function:
@csrf_exemptdef snippet_list(request): """ because we want to be able to POST to this view from clients that won't have a CSRF token we need to mark the view as csrf_exempt List all code snippets, or create a new snippet. """ if request.method == "GET": snippets = Snippet.objects.all() serializer = SnippetSerializer(snippets, many=True) return JsonResponse(serializer.data, safe=False) elif request.method == "POST": data = JSONParser().parse(request) serializer = SnippetSerializer(data=data) if serializer.is_valid(): serializer.save() return JsonResponse(serializer.data, status=201) return JsonResponse(serializer.errors, status=400)
That is to say, the json format needs to be specified during return, which is very impractical and simple, so the extended Reponse object is very convenient, it determines the correct content type based on the request header information of the client to return it to the client. You only need the following code:
<SPAN style="FONT-SIZE: 13px">return Response(data) # <SPAN style="COLOR: #ff0000">Renders to content type as requested by the client. </SPAN></SPAN>
Iii. Status Code
Do we know that various statuses will be returned when an http request is sent, but they are all simple numbers, such as 200 and 404, these pure numeric identifiers may not be clear enough, or the client may not be clear about the error message or even fail to see it, so django-rest-framework is also optimized, the status code will be HTTP_400_BAD_REQUEST and HTTP_404_NOT_FOUND, which greatly improves readability.
Iv. Packaging API View
The REST framework provides two wrappers for writing API views.
• @ Api_view decorator is used to process function-based views.
• The APIView class is used for view-based classes.
These packages provide some features, saving us a lot of work. For example, make sure that you receive the Request object in the view or add the context to your Response object to implement content communication.
In addition, the decorator can throw a ParseError exception when receiving an incorrect request. data, or return the 405 Method Not Allowed status code when appropriate.
5. Pulling it all together (used)
Okay, let's go ahead and start using these new components to write a few views.
We don't need our JSONResponse class in views. py any more, so go ahead and delete that. Once that's done we can start refactoring (refactoring) our views slightly.
In the views. py file, we no longer need our JSONResponse class, so we can continue to delete it. Once completed, we can start to slightly reconstruct our view.
from rest_framework import statusfrom rest_framework.decorators import api_viewfrom rest_framework.response import Responsefrom snippets.models import Snippetfrom 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)
It can be seen that the improved code has applied the features of several django-rest-framework mentioned above. We can see that the program code volume is reduced, in addition, more situations can be handled. For example, in the original view function snippet_detail, when processing a 'put' request, you need to parse the json format data sent from the front end before further processing:
<SPAN style="FONT-SIZE: 13px">data = JSONParser().parse(request) serializer = SnippetSerializer(snippet, data=data) </SPAN>
That is to say, we need to divide the implementation into two steps, and here there is a limit that only data streams in json format can be parsed. The improved program requires only one line of code:
<SPAN style="FONT-SIZE: 13px">serializer = SnippetSerializer(data=request.data) </SPAN>
Request. data can handle incoming json requests, but it can also handle other formats. similarly we're re returning response objects with data, but allowing REST framework to render the response into the correct content type for us.
Request. data can be used to obtain the submitted data and process various data and request actions, facilitating development. In addition, you do not need to specify the json format when returning, from the original:
<SPAN style="FONT-SIZE: 13px">return JsonResponse(serializer.data, status=201) </SPAN>
Changed
<SPAN style="FONT-SIZE: 13px">return Response(serializer.data,status=status.HTTP_201_CREATED) </SPAN>
This also means that the content returned to the client can be in json or html format. If HTML content is returned, the rendered and more beautiful pages will be returned in the browser. At the same time, we can see that the status code has also been improved to the django-rest-framework to give us a more readable status code. The above measures have greatly improved customer friendliness.
The same principle applies to the modification of another view function. The Code is as follows:
@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)
The above is an improvement to the conventional Django view function.
To sum up, the data submitted by the request does not need to be in json format, and the returned response does not need to be in json or rendered HTML pages. It will be demonstrated later.
6. Add an optional format suffix to the URL
Since the Response returned to the client is in json or HTML format, how do you specify the format of returned content, that is, add the suffix at the end of the URL. For example, http: // 127.0.0.1: 8000/snippets. json. The Response in json format is specified by the user rather than the fixed format specified in the background.
You only need to make some improvements to our program. Add the keyword parameter format in the two view functions:
def snippet_list(request, format=None):
And
def snippet_detail(request, pk, format=None):
Now update the urls. py file slightly, to append a set of format_suffix_patterns (format suffix mode) in addition to the existing URLs.
from django.conf.urls import urlfrom rest_framework.urlpatterns import format_suffix_patternsfrom snippets import viewsurlpatterns = [ url(r'^snippets/$', views.snippet_list), url(r'^snippets/(?P<pk>[0-9]+)$', views.snippet_detail),]urlpatterns = format_suffix_patterns(urlpatterns)
7. How's it looking?
Go ahead and test the API from the command line, as we did in tutorial part 1. Everything is working pretty similarly, although we 've got some nicer error handling if we send invalid requests.
We can get a list of all of the snippets, 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 control the format of the response that we get back, either by using the Accept header:
<SPAN style="FONT-SIZE: 13px">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</SPAN>
Or by appending a format suffix:
<SPAN style="FONT-SIZE: 13px">http http://127.0.0.1:8000/snippets.json # JSON suffix http http://127.0.0.1:8000/snippets.api # Browsable API suffix</SPAN>
Similarly, we can control the format of the request that we send, using the Content-Type header.
# POST using form datahttp --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 JSONhttp --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 add a -- debug switch to the http requests above, you will be able to see the request type in request headers.
Now go and open the API in a web browser, by visiting http: // 127.0.0.1: 8000/snippets /.
Browsability
Because the API chooses the content type of the response based on the client request, it will, by default, return an HTML-formatted representation of the resource when that resource is requested by a web browser. this allows for the API to return a fully web-browsable HTML representation.
Having a web-browsable API is a huge usability win, and makes developing and using your API much easier. it also dramatically lowers the barrier-to-entry for other developers wanting to inspect and work with your API.
See the browsable api topic for more information about the browsable API feature and how to mimize it.
Browsing function (Chinese)
Because the API selects the response content type based on the client request, by default, when a Web browser requests a resource, it returns the resource representation in HTML format. This allows the API to return a completely HTML representation of a Web page that can be viewed.
Having an API that allows you to browse Web pages is a huge victory in availability and makes it easier to develop and use your API. It also greatly reduces the entry barriers for other developers who want to check and use your APIs.
For more information about browsed APIs and how to customize them, see the topic of browsed APIs.
The request and response of the above django rest framework (detailed description) is all the content shared by the editor. I hope you can give us a reference and support for the customer's house.