• Django REST framework 第二章 Request and Response


    此章节开始真正的撰写REST framework的核心代码,介绍一系列必要的建立设计

    Request Objects

    REST framework介绍了一个Request对象用来扩展常规的HttpRequest,提供了更多灵活的请求解析。Request对象的核心功能是request.data属性跟request.POST非常相似,但是在WEB APIs方面更能发挥作用。

    request.POST  # 只处理表单数据,只能用于POST方法
    request.data  # 处理任意的数据,作用于POST、PUT、PATCH方法

    Response Objects

    REST framework还引入了一个响应对象Response,它是一种TemplateResponse类型,采用没有render内容和使用内容协商来确定正确的内容类型并返回给客户端.

    return Response(data)  # 转换到客户端需要的内容类型Renders to content type as requested by the client.

    Status codes

    使用数字HTTP状态码在你的视图内不会总是被明显的阅读到,并且很容易不被注意到,如果你拿到了一个错误的错误代码。REST framework提供了更多明确的标识符为每一个状态码,比如HTTP_400_BAD_REQUEST在状态模块单元里。相比于使用数字标识符,广泛使用这些是一个更好的主意。

    Wrapping API views

    REST framework提供了2种你可以使用来写API 视图的包装:

    1、@api_view装饰器为FBV服务

    2、APIView类为CBV服务

    这些封装提供了一些功能,比如确定你能接受到Request实例在视图中,添加上下文到Response对象从而可以进行内容协商转换。此外还提供了一些行为,比如返回405 Method Not Allowed返回值在合适的时候,当访问的request.data是很畸形的输入时处理任何ParseError错误

    Pulling it all together

    好了,现在开始使用这些新组件写一些视图。

    views.py文件中再不需要JSONResponse类,所以继续并删除掉它。一旦完成,就可以开始稍微重构视图。

    from app01.models import Snippet
    from app01.serializers import SnippetSerializer
    from rest_framework import status
    from rest_framework.decorators import api_view
    from rest_framework.response import Response
    
    @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)  # queryset对象,配合many=True
            return Response(serializer.data)
    
        elif request.method == 'POST':
            serializer = SnippetSerializer(data=request.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)

    我们的实例视图是前面的示例的一次改进。这是一个更简洁方案,并且感觉代码非常相似,如果我们正在使用表单API。我们也在使用被命名的状态码,这会让返回的含义更加明显。

    @api_view(['GET', 'PUT', 'DELETE'])
    def snippet_detail(request, pk):
        """
        获取、更新、删除
        """
        try:
            snippet = Snippet.objects.get(pk=pk)  # model类单个对象实例
        except Snippet.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)  # 未获取到信息
    
        if request.method == 'GET':
            serializer = SnippetSerializer(snippet)
            return Response(serializer.data)  # response内部解决了序列化问题 不需要再写JsonResponse(serializer.data, safe=False)
    
        elif request.method == 'PUT':
            serializer = SnippetSerializer(snippet, data=request.data)  # 跟form里面的更新操作也很类似
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data)  # 单个对象的data是一个字典,多个对象的是list,需要safe=False
            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或者response打上一个明确的内容类型. request.data可以处理即将到来的json请求,但它也可以处理其他格式的. 相似地也会返回带有数据的respose对象,但是允许REST framework为我们去转换response到正确的类型。

    Adding optional format suffixes to our URLs

    为了充分利用,事实上返回不在与单个内容类型硬连线,让我们添加对API端点的格式后缀的支持。使用格式后缀能显式地引用给定格式的URLs,意味着API将会能够处理URLs,比如http://example.com/api/items/4.json

    在之前的两个视图内都加上关键字参数format

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

    更新app内的url文件

    from app01 import views
    from django.urls import path, include
    from rest_framework.urlpatterns import format_suffix_patterns
    
    
    app_name = 'app01'
    urlpatterns = [
        path('snippets/', views.snippet_list),
        path('snippets/<int:pk>/', views.snippet_detail),
    ]
    urlpatterns = format_suffix_patterns(urlpatterns)

    我们不一定要加上这些额外的URL模式,但它为我们提供了一个简单的,指特定格式的清洁方式。

    如果按照之前的章节一步步做到这个遇到下面这个问题,请到setting里面把REST_FRAMEWORK注释掉,因为将之前的视图注释掉了,没有用到Django内置的auth,具体说不清,但是确实是那边功能缺失。

    注释掉此段:

    # REST_FRAMEWORK = {
    #     # Use Django's standard `django.contrib.auth` permissions,
    #     # or allow read-only access for unauthenticated users.
    #     'DEFAULT_PERMISSION_CLASSES': [
    #         'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    #     ]
    # }

    测试成效

    测试一下下面的后缀

    http http://127.0.0.1:8000/app01/snippets/ Accept:application/json  # Request JSON
    http http://127.0.0.1:8000/app01/snippets/ Accept:text/html         # Request HTML
    http http://127.0.0.1:8000/app01/snippets.json  # JSON suffix
    http http://127.0.0.1:8000/app01/snippets.api   # Browsable API suffix

    相似的,我们可以控制发送的请求的格式,使用Content-Type 头。

    http --json POST http://127.0.0.1:8000/app01/snippets/ "code=11"

    如果添加--debug在上面的额http请求,你讲可以看到请求类型在请求头里面。同样的也可以在web浏览器里访问

  • 相关阅读:
    排序去重
    $(...)[0].attr is not a function问题
    daterangepicker的汉化和简单使用
    wx.openSetting的调整
    css3中-moz、-ms、-webkit与盒子模型
    动态翻滚的导航条
    CSS3 transition 浏览器兼容性
    jq实现两个input输入同时不为空时,改变确认框背景颜色
    js 监听input 实现数据绑定
    关于html 修改滚动条的问题
  • 原文地址:https://www.cnblogs.com/wuzdandz/p/9456851.html
Copyright © 2020-2023  润新知