本文共 5013 字,大约阅读时间需要 16 分钟。
Django视图是用来处理请求和响应的核心组件,默认使用Form和Template设计。然而,当开发RESTful API时,需要对Django的请求和响应处理逻辑进行优化。DRF(Django REST Framework)提供了丰富的功能,可以帮助我们更高效地构建API。以下是关于DRF在视图优化方面的一些实用技巧和改造方法。
DRF对HttpRequest进行了扩展,提供了更强大的Request对象。request.data是DRF的核心属性,它与request.POST的主要区别在于支持多种HTTP方法(如POST、PUT、PATCH)处理非表单数据,而不仅仅是处理表单数据。
| 属性 | 描述 |
|---|---|
request.data | 支持多种HTTP方法的数据处理,支持JSON、表单数据等。 |
request.POST | 只处理表单数据,仅适用于POST方法。 |
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 在开发过程中,使用数字形式的状态码(如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模块中找到。
DRF提供了两种主要的API视图装饰器:
@api_view:用于装饰函数视图,支持多种HTTP方法(如GET、POST、PUT等)。APIView:用于装饰类视图,提供了更多高级功能。Request类型。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) 通过命令测试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/
DRF自动生成API文档,可以直接在浏览器中查看:
python manage.py drfdocs
或者访问http://your-site.com/docs/
DRF通过Request和Response的优化、状态码标识符、api_view装饰器等功能,显著提升了Django开发RESTful API的效率和体验。通过上述改造,您可以快速构建高效的API接口,并通过DRF自动生成文档,降低开发和维护成本。
转载地址:http://ouyuz.baihongyu.com/