• API(二)之Requests and Responses


    这一部分可以让返回的api信息以两种格式呈现:.json和.api

    REST框架的核心部分。我们来介绍几个基本的组成部分。

    Request objects

    REST框架引入了Request对象来扩展常规的HttpRequest,并提供更灵活的请求解析。Request对象的核心功能request.data属性,它与request.POST相似,但对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 objects

    REST框架还引入了Response对象,which is a type of TemplateResponse that takes unrendered content and uses content negotiation to determine the correct content type to return to the client.

    return Response(data)  # Renders to content type as requested by the client.
    

    Status codes

    在您的视图中使用数字HTTP状态码并不总是利于阅读,如果您收到 an error code wrong你将很难注意到。 REST框架为每一个状态码更明确的标识符,如status模块中的HTTP_400_BAD_REQUEST。 使用这些标识符比使用数字标识符要好的多。

    HTTP_100_CONTINUE = 100
    HTTP_101_SWITCHING_PROTOCOLS = 101
    HTTP_200_OK = 200
    HTTP_201_CREATED = 201
    HTTP_202_ACCEPTED = 202
    HTTP_203_NON_AUTHORITATIVE_INFORMATION = 203
    HTTP_204_NO_CONTENT = 204
    HTTP_205_RESET_CONTENT = 205
    HTTP_206_PARTIAL_CONTENT = 206
    HTTP_207_MULTI_STATUS = 207
    HTTP_300_MULTIPLE_CHOICES = 300
    HTTP_301_MOVED_PERMANENTLY = 301
    HTTP_302_FOUND = 302
    HTTP_303_SEE_OTHER = 303
    HTTP_304_NOT_MODIFIED = 304
    HTTP_305_USE_PROXY = 305
    HTTP_306_RESERVED = 306
    HTTP_307_TEMPORARY_REDIRECT = 307
    HTTP_400_BAD_REQUEST = 400
    HTTP_401_UNAUTHORIZED = 401
    HTTP_402_PAYMENT_REQUIRED = 402
    HTTP_403_FORBIDDEN = 403
    HTTP_404_NOT_FOUND = 404
    HTTP_405_METHOD_NOT_ALLOWED = 405
    HTTP_406_NOT_ACCEPTABLE = 406
    HTTP_407_PROXY_AUTHENTICATION_REQUIRED = 407
    HTTP_408_REQUEST_TIMEOUT = 408
    HTTP_409_CONFLICT = 409
    HTTP_410_GONE = 410
    HTTP_411_LENGTH_REQUIRED = 411
    HTTP_412_PRECONDITION_FAILED = 412
    HTTP_413_REQUEST_ENTITY_TOO_LARGE = 413
    HTTP_414_REQUEST_URI_TOO_LONG = 414
    HTTP_415_UNSUPPORTED_MEDIA_TYPE = 415
    HTTP_416_REQUESTED_RANGE_NOT_SATISFIABLE = 416
    HTTP_417_EXPECTATION_FAILED = 417
    HTTP_422_UNPROCESSABLE_ENTITY = 422
    HTTP_423_LOCKED = 423
    HTTP_424_FAILED_DEPENDENCY = 424
    HTTP_428_PRECONDITION_REQUIRED = 428
    HTTP_429_TOO_MANY_REQUESTS = 429
    HTTP_431_REQUEST_HEADER_FIELDS_TOO_LARGE = 431
    HTTP_451_UNAVAILABLE_FOR_LEGAL_REASONS = 451
    HTTP_500_INTERNAL_SERVER_ERROR = 500
    HTTP_501_NOT_IMPLEMENTED = 501
    HTTP_502_BAD_GATEWAY = 502
    HTTP_503_SERVICE_UNAVAILABLE = 503
    HTTP_504_GATEWAY_TIMEOUT = 504
    HTTP_505_HTTP_VERSION_NOT_SUPPORTED = 505
    HTTP_507_INSUFFICIENT_STORAGE = 507
    HTTP_511_NETWORK_AUTHENTICATION_REQUIRED = 511

    Wrapping API views

    REST框架提供了两个可用于编写API视图的wrappers。

    1. 适用于function-based views的@api_view 。
    2. 适用于class-based views的APIView 。

    这些wrappers提供了一些功能,例如确保您在视图中接收Request实例,并将上下文添加到Response对象,以便可以执行content negotiation。

    The wrappers also provide behaviour such as returning 405 Method Not Allowed responses when appropriate, and handling any ParseError exception that occurs when accessing request.data with malformed input.

    Pulling it all together

    好的,我们开始使用这些新的组件来写几个视图。

     views.py中不再需要JSONResponse class, 所以请删除它。一旦完成这些,我们就可以开始重构我们视图了.

    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 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)
    

    我们的实例视图比以前的例子有所改进。这更加简明扼要,现在的代码与我们使用的Forms API非常相似。我们还使用命名的状态码,这使得响应意义更加明显。

    以下是views.py模块中单个的代码段视图。

    @api_view(['GET', 'PUT', 'DELETE'])
    def snippet_detail(request, pk):
        """
        Retrieve, update or delete a snippet instance.
        """
        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)
    

    这应该都是非常熟悉的 - 与常规的Django视图并没有什么不同。

    请注意,我们不再明确地将我们的请求或响应绑定到一个给定的内容类型。request.data 能够处理输入的 json requests,但它也可以处理其他格式。同样,we're returning response objects with data,但允许REST框架将响应渲染成正确的内容类型。

    给url添加可选的格式后缀

    我们的响应不再与单一内容类型连接,为了充分利用这个事实,我们可以为API端点添加一些格式后缀。使用格式后缀给urls明确指定一个格式,这意味着我们的API将能处理诸如http://example.com/api/items/4.json之类的urls

    首先给两个视图添加关键字参数format ,就像这样。

    def snippet_list(request, format=None):
    

    and

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

    然后更新urls.py文件,给已经存在的urls附加一组format_suffix_patterns

    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)
    

    我们不是一定要添加这些额外的url模式,但它给了我们一个简单、干净的方式来引用特定的格式。

    How's it looking?

    在命令行中测试API,就像我们在第1部分中所做的那样。一切工作都非常相似,尽管如果发送无效请求,我们已经有了更好的错误处理。

    我们可以像以前一样获取所有片段的列表。

    http http://127.0.0.1:8000/snippets/
    
    HTTP/1.1 200 OK
    ...
    [
      {
        "id": 1,
        "title": "",
        "code": "foo = "bar"
    ",
        "linenos": false,
        "language": "python",
        "style": "friendly"
      },
      {
        "id": 2,
        "title": "",
        "code": "print "hello, world"
    ",
        "linenos": false,
        "language": "python",
        "style": "friendly"
      }
    ]
    

    我们可以通过使用Accept header来控制响应的格式

    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
    

    或者通过附加格式后缀:

    http http://127.0.0.1:8000/snippets.json  # JSON suffix
    http http://127.0.0.1:8000/snippets.api   # Browsable API suffix
    

    类似地,我们可以使用Content-Type header来控制我们发送的请求的格式。

    # 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"
    }

    如果您向上述的http requests添加--debug,你将可以在请求头中查看请求类型。

    现在,在Web浏览器中打开API,访问http://127.0.0.1:8000/snippets/

  • 相关阅读:
    linux 安全组
    php 类
    linux安装phpmyadmin
    mysql设置对外访问
    linux 防火墙
    微信小程序之swiper组件高度自适应
    Thinkphp5 关联模型
    README.md文件编辑
    linux安装mysql
    小程序返回顶部top滚动
  • 原文地址:https://www.cnblogs.com/yangxiaoling/p/6907916.html
Copyright © 2020-2023  润新知