Django Rest Framework: further understanding of serialization of function-based views

One, the request object Request

REST framework introduces an extension from the conventional HttpRequest object, Request 对象and adds support for REST framework's flexible request parsing and request authentication.
The core function of the Request object is request.data 属性that it is similar to request.POST, but it is more useful for using Web API.

  • request.POST only processes form data. Only applicable to the'POST' method.
  • request.data handles arbitrary data. Applicable to'POST','PUT' and'PATCH' methods.

1. Request resolution

The request object of the REST framework provides flexible request parsing, allowing JSON data or other media types to be processed in the same way as form data is usually processed.
1. .data:
request.datareturns the parsed content of the request body. This is similar to the standard request.POST and request.FILES properties, but there are also differences:

  • It includes all parsed content, including file and non-file input.
  • It supports parsing the content of HTTP methods other than POST, which means that the content of PUT and PATCH requests can be accessed.
  • It supports flexible request parsing of REST framework, not just form data. For example, the way to process incoming JSON data is the same as the way to process incoming form data.
  • For more details, please refer to the official API: Parser .

2. .query_params:
request.query_params is a more correct naming synonym for request.GET.
In order to make the code clearer, the official recommendation is to use request.query_params instead of Django's standard request.GET. Doing so helps to make the code base more correct and obvious-any HTTP method type may contain query parameters, not just GET requests.
3. Parser: The
APIView class or @api_view decorator will ensure that the property is automatically set to the list of parser instances according to the parser class set on the view or the default parser class setting.

  • If the client sends incorrectly formatted content, accessing request.data may cause ParseError. By default, REST framework's APIView class or @api_view decorator will catch errors and return a 400 Bad Request response.
  • If the content type of the request sent by the client cannot be parsed, an UnsupportedMediaType exception will be raised. By default, it will be caught and a 415 Unsupported Media Type response will be returned.

2. Content negotiation

The request discloses some attributes that allow you to determine the outcome of the content negotiation phase. This allows some behaviors, such as choosing different serialization schemes for different media types.
1 .accepted_renderer.: The
renderer instance is selected by the content negotiation stage.
2. .accepted_media_type:
A string representing the media type accepted during the content negotiation phase.

3. Authentication (Authentication)

The REST framework provides flexible per-request authentication, which enables:

  • Use different authentication strategies for different parts of the API.
  • Support the use of multiple authentication strategies.
  • Provide the user and token information associated with the incoming request.
    1. .user:
    request.user usually returns an instance of django.contrib.auth.models.User, but its behavior depends on the authentication strategy being used.
  • If the request is not authenticated, the default value of request.user is an instance of django.contrib.auth.models.AnonymousUser. For more details, please refer to the official API: Certification .
    2. .auth:
    request.auth returns any additional authentication context. The exact behavior of request.auth depends on the authentication strategy being used, but it may usually be an instance of a token requesting authentication.
  • If the request is unauthenticated, or there is no additional context, the default value of request.auth is None.
    3. .authenticators: The
    APIView class or @api_view decorator will ensure that this attribute is automatically set to the Authentication instance list according to the authentication_classes set on the view or the DEFAULT_AUTHENTICATORS setting.

4. Browser enhancement

REST framework supports some browser enhancements, such as browser-based PUT, PATCH and DELETE forms.
1. .method:
request.method returns the request HTTP method represented by an uppercase string.

2. .content_type:
request.content_type returns a string object representing the media type of the HTTP request body, or an empty string if no media type is provided.

  • If you need to access the requested content type, you should use the .content_type attribute in preference to request.META.get('HTTP_CONTENT_TYPE'), because it provides transparent support for browser-based non-form content.
    3. .stream:
    request.stream returns a stream representing the content of the request body.

Second, the response object Response

REST framework also introduced one Response 对象, which is a TemplateResponse type that retrieves unrendered content and uses content negotiation to determine the correct content type to return to the client.

The subclass of the Response class is Django's SimpleTemplateResponse. The response object is initialized with data, which should consist of native Python primitives. REST framework then uses standard HTTP content negotiation to determine how it will render the final response content. There is no need to use the Response class, and if necessary, you can also return a regular HttpResponse or StreamingHttpResponse object from the view. Using the Response class just provides a better interface for returning Web API responses for content negotiation. These responses can be rendered in multiple formats.

  • Unless for some reason you need a lot of custom REST framework, otherwise it should always be used to return the Response object view API​​View 类or @api_viewfunction. Doing so ensures that the view performs content negotiation and selects the appropriate renderer for the response before the view returns.

1. Create a response

grammar:Response(data, status=None, template_name=None, headers=None, content_type=None)

  • data : The serialized data of the response.
  • status: The status code of the response. The default is 200.
  • template_name: The name of the template used when selecting HTMLRenderer.
  • headers: A dictionary of HTTP headers used in the response.
  • content_type: The content type of the response. Normally, the renderer is automatically set based on the result of content negotiation, but in some cases, the content type needs to be specified explicitly.
  • If unrendered data is passed, it can be composed of any Python primitives.
  • Since Response class using the renderer can not handle complex data types , e.g. Django model instance, it is necessary before creating Response object should first data sequence to primitives .

2. Properties

1. The
unrendered, serialized response data of .data .
2. .status_code
The digital status code of the HTTP response.
3.
The rendered content of the .content response. Before accessing .content, the .render() method must be called.
4. .template_name
template_name (if provided). Only needed if HTMLRenderer or other custom template renderer is a responsive renderer.
5. .accepted_renderer is
used to render the response renderer instance. It is automatically set by APIView or @api_view before returning the response from the view.
6. Accepted_media_type
The media type selected during content negotiation. It is automatically set by APIView or @api_view before returning the response from the view.
7. .renderer_context
will be a dictionary of additional context information passed to the renderer's .render() method. It is automatically set by APIView or @api_view before returning the response from the view.

Three, the status code

Using digital HTTP status codes in your views is not always conducive to the reading of the code. If you write the code wrong, it is easy to be ignored. REST framework provides a more specific identifier for each status code, such as in the status module HTTP_400_BAD_REQUEST. It is a good idea to use them instead of using numeric identifiers.

1. Information-1xx (Informational-1xx)

This type of status code indicates a provisional response. By default, 1xx status codes are not used in REST framework.

TTP_100_CONTINUE
HTTP_101_SWITCHING_PROTOCOLS

2. Success-2xx (Successful-2xx)

This type of status code indicates that the client's request has been successfully received, understood and accepted.

HTTP_200_OK
HTTP_201_CREATED
HTTP_202_ACCEPTED
HTTP_203_NON_AUTHORITATIVE_INFORMATION
HTTP_204_NO_CONTENT
HTTP_205_RESET_CONTENT
HTTP_206_PARTIAL_CONTENT
HTTP_207_MULTI_STATUS

3. Redirection-3xx (Redirection-3xx)

This type of status code indicates that the user agent needs to take further action to satisfy the request.

HTTP_300_MULTIPLE_CHOICES
HTTP_301_MOVED_PERMANENTLY
HTTP_302_FOUND
HTTP_303_SEE_OTHER
HTTP_304_NOT_MODIFIED
HTTP_305_USE_PROXY
HTTP_306_RESERVED
HTTP_307_TEMPORARY_REDIRECT

4. Client Error-4xx (Client Error-4xx)

The 4xx status codes are for situations where the client seems to have gone wrong. In addition to responding to a HEAD request, the server should include an entity that contains an explanation of the error condition and whether it is temporary or permanent.

HTTP_400_BAD_REQUEST
HTTP_401_UNAUTHORIZED
HTTP_402_PAYMENT_REQUIRED
HTTP_403_FORBIDDEN
HTTP_404_NOT_FOUND
HTTP_405_METHOD_NOT_ALLOWED
HTTP_406_NOT_ACCEPTABLE
HTTP_407_PROXY_AUTHENTICATION_REQUIRED
HTTP_408_REQUEST_TIMEOUT
HTTP_409_CONFLICT
HTTP_410_GONE
HTTP_411_LENGTH_REQUIRED
HTTP_412_PRECONDITION_FAILED
HTTP_413_REQUEST_ENTITY_TOO_LARGE
HTTP_414_REQUEST_URI_TOO_LONG
HTTP_415_UNSUPPORTED_MEDIA_TYPE
HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE
HTTP_417_EXPECTATION_FAILED
HTTP_422_UNPROCESSABLE_ENTITY
HTTP_423_LOCKED
HTTP_424_FAILED_DEPENDENCY
HTTP_428_PRECONDITION_REQUIRED
HTTP_429_TOO_MANY_REQUESTS
HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE
HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS

5. Server Error-5xx (Server Error-5xx)

The response status code starting with the number "5" indicates that the server realizes that it has been wrong or cannot execute the request. In addition to responding to a HEAD request, the server should include an entity that contains an explanation of the error condition and whether it is temporary or permanent.

HTTP_500_INTERNAL_SERVER_ERROR
HTTP_501_NOT_IMPLEMENTED
HTTP_502_BAD_GATEWAY
HTTP_503_SERVICE_UNAVAILABLE
HTTP_504_GATEWAY_TIMEOUT
HTTP_505_HTTP_VERSION_NOT_SUPPORTED
HTTP_507_INSUFFICIENT_STORAGE
HTTP_511_NETWORK_AUTHENTICATION_REQUIRED

6. Helper functions

The following helper functions can be used to identify the category of response codes.

is_informational()  # 1xx
is_success()        # 2xx
is_redirect()       # 3xx
is_client_error()   # 4xx
is_server_error()   # 5xx

Fourth, wrap API serialized views (Wrapping API views)

The REST framework provides two wrappers that can be used to write API views:

  1. Used for function-based views @api_view 装饰器. @api_view source code is in tutorial\venv\Lib\site-packages\rest_framework\decorators.py. That is, if you use the view function to develop the API interface, you must use the @api_view decorator for the view function.
  2. Used for class-based views APIView 类. The source code of APIView is in tutorial\venv\Lib\site-packages\rest_framework\views.py. That is, if the view class is used to develop the API interface, the view class inherits the APIView class.

Five, function-based view

REST framework allows the use of conventional function-based views. It provides a set of simple decorators to wrap function-based views to ensure that they receive Request (rather than the usual Django HttpRequest) instance, allow them to return Response (rather than Django HttpResponse), and configure the processing of the request the way.

1,@api_view()

Syntax: @api_view(['GET', 'POST', .......])
The core of a function-based view is the api_view decorator, which accepts a list of HTTP methods that the view should respond to.
By default, only the GET method will be accepted. Other methods will respond with "405 Method Not Allowed". But it can be changed:

@api_view(['GET', 'POST'])
def hello_world(request):
    if request.method == 'POST':
        return Response({
    
    "message": "Got some data!", "data": request.data})
    return Response({
    
    "message": "Hello, world!"})
  • The view will use the default renderer, parser, authentication class, etc. specified in the settings .

2. API policy decorators

In order to override the default settings, REST framework provides a series of additional decorators that can be added to the view. These must be after the @api_view decorator.

要创建一个使用限流来确保它每天只能由特定用户调用一次的视图,请使用 @throttle_classes 装饰器,传递一个限流类列表:
from rest_framework.decorators import api_view, throttle_classes
from rest_framework.throttling import UserRateThrottle

class OncePerDayUserThrottle(UserRateThrottle):
        rate = '1/day'

@api_view(['GET'])
@throttle_classes([OncePerDayUserThrottle])
def view(request):
    return Response({
    
    "message": "Hello for today! See you tomorrow!"})

The available decorators are:

  • @renderer_classes(…)
  • @parser_classes(…)
  • @authentication_classes(…)
  • @throttle_classes(…)
  • @permission_classes(…)

Six, use function-based views

1. Refactor function-based views

@api_view(['GET', 'POST'])
def snippet_list(request):
    """
    列出所有的代码 snippet,或创建一个新的 snippet。
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True) #前面提到,data部分既可以是模型内容,也可以是查询集
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = SnippetSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()	# 验证无误后,存入模型数据库
            print(serializer)
            return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
    """
    获取,更新或删除一个代码 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)
  • Both use Resopnse to make the content more readable, that is, to return the response object with data, which allows REST framework to render the response into the correct content type.
  • The specified status code is used, which makes the response more obvious.
  • No longer explicitly bind the request or response to the specified type. request.data can handle incoming requests in multiple formats,

2. Add an optional format suffix to the URL

To take advantage of the fact that our response is no longer hardwired to a single content type, we can add support for format suffixes to our API endpoints.
Using the format suffix provides us with a URL that clearly points to a given format, such as http://example.com/api/items/4.json.
1. Add a parameter to both view functions, format=None:

def snippet_list(request, format=None):
def snippet_detail(request, pk, format=None):

2. Add format_suffix_patterns to the urls in snippet/urls.py file:

from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

urlpatterns = [
    url(r'^snippets/$', views.snippet_list),
    url(r'^snippets/(?P<pk>[0-9]+)$', views.snippet_detail),
]

urlpatterns = format_suffix_patterns(urlpatterns)

3. Run:
Insert picture description here
Insert picture description here
Insert picture description here
Insert picture description here

Guess you like

Origin blog.csdn.net/dangfulin/article/details/108177047