博客
关于我
DRF对Django请求响应做了技术升级
阅读量:422 次
发布时间:2019-03-06

本文共 4940 字,大约阅读时间需要 16 分钟。

Django REST Framework(DRF)视图优化改造指南

Django视图是用来处理请求和响应的核心组件,默认使用Form和Template设计。然而,当开发RESTful API时,需要对Django的请求和响应处理逻辑进行优化。DRF(Django REST Framework)提供了丰富的功能,可以帮助我们更高效地构建API。以下是关于DRF在视图优化方面的一些实用技巧和改造方法。


Request

DRF对HttpRequest进行了扩展,提供了更强大的Request对象。request.data是DRF的核心属性,它与request.POST的主要区别在于支持多种HTTP方法(如POST、PUT、PATCH)处理非表单数据,而不仅仅是处理表单数据。

属性 描述
request.data 支持多种HTTP方法的数据处理,支持JSON、表单数据等。
request.POST 只处理表单数据,仅适用于POST方法。

Response

DRF的Response类继承自Django的SimpleTemplateResponse,提供了更灵活的响应渲染功能。开发者可以根据客户端请求的内容类型(media type)动态选择合适的渲染器。

@propertydef rendered_content(self):    renderer = getattr(self, 'accepted_renderer', None)    accepted_media_type = getattr(self, 'accepted_media_type', None)    context = getattr(self, 'renderer_context', None)    assert renderer, ".accepted_renderer not set on Response"    assert accepted_media_type, ".accepted_media_type not set on Response"    assert context is not None, ".renderer_context not set on Response"    context['response'] = self    media_type = renderer.media_type    charset = renderer.charset    content_type = self.content_type    if content_type is None and charset is not None:        content_type = f"{media_type}; charset={charset}"    elif content_type is None:        content_type = media_type    self['Content-Type'] = content_type    ret = renderer.render(self.data, accepted_media_type, context)    if isinstance(ret, str):        assert charset, ("renderer returned unicode, and did not specify a charset value.")        return ret.encode(charset)    if not ret:        del self['Content-Type']    return ret

Status Codes

在开发过程中,使用数字形式的状态码(如400)不够直观。DRF提供了一系列易于阅读的状态码标识符,例如:

标识符 对应的状态码 描述
HTTP_200_OK 200 请求成功
HTTP_201_CREATED 201 资源已创建
HTTP_204_NO_CONTENT 204 请求成功但没有内容返回
HTTP_400_BAD_REQUEST 400 不合法的请求
HTTP_401_UNAUTHORIZED 401 未授权
HTTP_403_FORBIDDEN 403 被禁止
HTTP_404_NOT_FOUND 404 资源未找到
HTTP_405_METHOD_NOT_ALLOWED 405 方法不允许
HTTP_500_INTERNAL_SERVER_ERROR 500 内部服务器错误
HTTP_502_BAD_GATEWAY 502 网关错误
HTTP_503_SERVICE_UNAVAILABLE 503 服务暂时不可用
HTTP_504_GATEWAY_TIMEOUT 504 网关超时

所有状态码标识符都可以在rest_framework.status模块中找到。


API View和APIView

DRF提供了两种主要的API视图装饰器:

  • @api_view:用于装饰函数视图,支持多种HTTP方法(如GET、POST、PUT等)。
  • APIView:用于装饰类视图,提供了更多高级功能。
  • 核心功能

    • 请求类型检查:确保请求对象是Request类型。
    • 上下文添加:将视图实例添加到响应的上下文中。
    • 错误处理:自动处理405方法不允许等错误。
    • 数据解析:在数据格式错误时,抛出ParseError异常。

    改造views.py

    以下是改造后的snippets/views.py代码示例:

    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):    """获取所有代码段或创建新代码段."""    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)@api_view(['GET', 'PUT', 'DELETE'])def snippet_detail(request, pk):    """获取、更新或删除代码段."""    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)

    改动点

  • 使用@api_view装饰器:简化了视图的HTTP方法声明。
  • 使用状态码标识符:例如status.HTTP_404_NOT_FOUND
  • 使用request.data:替代了传统的JSONParser().parse(request),自动处理JSON数据。
  • 使用Response():替代JsonResponse(), 支持动态内容类型。

  • 添加格式后缀(可选)

    为了支持文件扩展名(如.json),可以在URL路由中添加格式后缀。首先修改视图函数:

    def snippet_list(request, format=None):    # ...函数逻辑...
    def snippet_detail(request, pk, format=None):    # ...函数逻辑...

    然后更新snippets/urls.py

    from django.urls import pathfrom rest_framework.urlpatterns import format_suffix_patternsfrom snippets import viewsurlpatterns = [    path('snippets/', views.snippet_list),    path('snippets/
    /', views.snippet_detail),]urlpatterns = format_suffix_patterns(urlpattern)

    测试API

    通过命令测试REST API:

    # 获取所有代码段curl http://127.0.0.1:8000/snippets/# 创建新代码段(使用form数据)curl --form "code=print(123)" http://127.0.0.1:8000/snippets/# 创建新代码段(使用JSON数据)curl --json "code=print(456)" http://127.0.0.1:8000/snippets/

    API文档

    DRF自动生成API文档,可以直接在浏览器中查看:

    python manage.py drfdocs

    或者访问http://your-site.com/docs/


    总结

    DRF通过RequestResponse的优化、状态码标识符、api_view装饰器等功能,显著提升了Django开发RESTful API的效率和体验。通过上述改造,您可以快速构建高效的API接口,并通过DRF自动生成文档,降低开发和维护成本。

    转载地址:http://ouyuz.baihongyu.com/

    你可能感兴趣的文章
    R3LIVE开源项目常见问题解决方案
    查看>>
    php缃戠珯,www.wfzwz.com
    查看>>
    php缓存查询函数
    查看>>
    php编写TCP服务端和客户端程序
    查看>>
    php编码规范
    查看>>
    PHP编码规范-PSR1、psr2 /psr3 psr4
    查看>>
    PHP编程效率的20个要点
    查看>>
    PHP网页缓存技术优点及代码
    查看>>
    PHP自动化测试(一)make test 和 phpt
    查看>>
    php自定义函数: 文件大小转换成智能形式
    查看>>
    php英语单词,php常用英语单词,快速学习php编程英语(6)
    查看>>
    R3.4.0安装包时报错“需要TRUE/FALSE值的地方不可以用缺少值”,需升级到R3.5.0
    查看>>
    PHP获取curl传输进度
    查看>>
    PHP获取IP所在地区(转)
    查看>>
    PHP获取IP的方法对比
    查看>>
    php获取json里面内容
    查看>>
    R2的版本由来
    查看>>
    PHP获取图片宽度高度、大小尺寸、图片类型、用于布局的img属性
    查看>>
    PHP获取当前文件的绝对路径
    查看>>
    PHP获取当前时间、时间戳的各种格式写法汇总
    查看>>