• Django-Rest-Framework 教程: 2. Requests 和 Responses


    接着上篇的内容, 本篇中, 我们进一步介绍Django-rest-framework的其他核心部件. 首先我们来做准备工作:

    Request

    django-rest-framework中引入了新的Request类, 该Request继承自Django的HttpRequest, 并提供了更多灵活的request处理功能. 比如request.DATA属性便是专门用作Web API的属性, 类似于request.POST.

        request.POST  # 只处理form数据; 只接受HTML 'POST'动作.
        request.DATA  # 处理特定数据; 接受HTML 'POST', 'PUT' 和 'PATCH' 动作.

    状态码 (status codes)

    django-rest-framework为每一个状态码都提供了打包好的, 更为精确的状态码完整描述供我们使用, 比如HTTP_400_BAD_REQUEST.

    API views

    django-rest-framework为function_based_view和class_based_view分别提供了@api_view修饰器和APIView类. 这些wrapper代码, 保证了view接收Request实例, 并会自动添加context至Response中. 这些wrapper还能自动返回正确的状态码和详细信息.

    1. 开始

    接着之前的views.py, 在这里, 我们已经不需要JSONResponse了, 因此, 首先将其删除. 然后修改views.py中的snippet_list view:

        snippets/views.py
        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):
            """
            展示所有存在的snippet, 或建立新的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)

    以上代码相对于教程1中的代码更为简洁. 可以看到代码与form API的使用十分相似, 我们还使用了内置的状态码, 使返回的response意义更为清晰.

    对于单独的snippet编辑:

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

    从以上代码中可以看到, 我们不再指明request和response中的内容类型. request.DATA即可用来处理json数据类型类型, 也可以处理yaml或其他数据类型. 同时, django-rest-framework也能根据不同情况, 再response呈现正确的数据类型.

    2. 使用其他数据格式

    为了展示如何多数据格式的支持, 接下来, 我们为url添加后缀: http://example.com/api/items/4.json

    为snippets/view.py中的snippet_list和snippet_detail增加format参数

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

    更新urls.py:

        from django.conf.urls import patterns, url
        from rest_framework.urlpatterns import format_suffix_patterns
    
        urlpatterns = patterns('snippets.views',
            url(r'^snippets/$', 'snippet_list'),
            url(r'^snippets/(?P<pk>[0-9]+)$', 'snippet_detail'),
        )
    
        urlpatterns = format_suffix_patterns(urlpatterns)

    以上代码是可选的, 实际上我们并不需要添加这些url pattern就能实现多数据格式的支持. 但添加之后使得使用时更加直观.

    3. 测试

    我们可以通过前篇教程中的方式测试, 获取所有snippet:

    curl http://127.0.0.1:8000/snippets/
    
    [{"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头部信息控制response返回格式:

        curl http://127.0.0.1:8000/snippets/ -H 'Accept: application/json'  # JSON
        curl http://127.0.0.1:8000/snippets/ -H 'Accept: text/html'         # HTML

    或者使用后缀控制返回格式:

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

    通过修改request的Content-Type头部, 控制格式:

        # 使用form data POST
        curl -X POST http://127.0.0.1:8000/snippets/ -d "code=print 123"
    
        {"id": 3, "title": "", "code": "print 123", "linenos": false, "language": "python", "style": "friendly"}
    
        # 使用JSON POST
        curl -X POST http://127.0.0.1:8000/snippets/ -d '{"code": "print 456"}' -H "Content-Type: application/json"
    
        {"id": 4, "title": "", "code": "print 456", "linenos": true, "language": "python", "style": "friendly"}

    或者直接在浏览器中打开:

        http://127.0.0.1:8000/snippets/

    原文链接: http://www.weiguda.com/blog/20/

  • 相关阅读:
    php socket 模型及效率问题
    深入浅出讲解:php的socket通信
    发现一个nginx LUA开发Web App的框架
    centos6.x 抓取ssh登录的用户名和密码
    使用Lua的扩展库LuaSocket用例
    Lua开发
    ngx.location.capture 只支持相对路径,不能用绝对路径
    PHP获得数组的交集与差集
    php用explode,可以提供多个字符作为分割符来进行分割数组吗?
    resizable可调整尺寸组件
  • 原文地址:https://www.cnblogs.com/leo23/p/5051907.html
Copyright © 2020-2023  润新知