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

本文共 5013 字,大约阅读时间需要 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)动态选择合适的渲染器。

@property
def 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 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):
    """获取所有代码段或创建新代码段."""
    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 path
    from rest_framework.urlpatterns import format_suffix_patterns
    from snippets import views
    urlpatterns = [
    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/

    你可能感兴趣的文章
    Objective-C实现Queue队列算法(附完整源码)
    查看>>
    Objective-C实现Queue队列算法(附完整源码)
    查看>>
    Objective-C实现quick select快速选择算法(附完整源码)
    查看>>
    Objective-C实现rabin-karp算法(附完整源码)
    查看>>
    Objective-C实现radians弧度制算法(附完整源码)
    查看>>
    Objective-C实现radianToDegree弧度到度算法(附完整源码)
    查看>>
    Objective-C实现radix sort基数排序算法(附完整源码)
    查看>>
    Objective-C实现rail fence围栏密码算法(附完整源码)
    查看>>
    Objective-C实现rayleigh quotient瑞利商算法(附完整源码)
    查看>>
    Objective-C实现RC4加解密算法(附完整源码)
    查看>>
    Objective-C实现RC4加解密算法(附完整源码)
    查看>>
    Objective-C实现recursive bubble sor递归冒泡排序算法(附完整源码)
    查看>>
    Objective-C实现recursive insertion sort递归插入排序算法(附完整源码)
    查看>>
    Objective-C实现recursive quick sort递归快速排序算法(附完整源码)
    查看>>
    Objective-C实现RedBlackTree红黑树算法(附完整源码)
    查看>>
    Objective-C实现redis分布式锁(附完整源码)
    查看>>
    Objective-C实现regular-expression-matching正则表达式匹配算法(附完整源码)
    查看>>
    Objective-C实现relu线性整流函数算法(附完整源码)
    查看>>
    Objective-C实现restful api服务(附完整源码)
    查看>>
    Objective-C实现reverse letters反向字母算法(附完整源码)
    查看>>