Django REST framework 學習筆記(二)
-
- Request對象
- Response對象
- 狀态碼
- 包裝API視圖
- 使用@api_view編寫API視圖
- 使用APIView編寫視圖
Request對象
- REST framework 引入了一個
對象,它是對Request
的擴充,并提供靈活的請求解析HttpRequest
-
對象的核心功能是Request
,它類似于request.data
,但對于使用Web API更加有用request.POST
request.POST # 隻能操作 form表單 資料,隻能用于 'POST' 方法
request.data # 可以操作任意的資料,并且能用于 'POST'、'PUT'、'PATCH' 方法
Response對象
- REST framework 還引入了一個
對象,它是一種Response
對象TemplateResponse
- 它能夠使用協商好的類型,根據用戶端請求的内容類型,呈現給用戶端該類型的内容
- 例如:用戶端請求
類型的資料,則呈現給用戶端json
類型資料json
狀态碼
- 使用數字HTTP狀态碼并不能總是正确的顯示出讀數,如果代碼是錯誤的的話
- REST framework 為每個狀态碼提供了專門的辨別符,放在了
子產品中status
- 例如:
,表示狀态碼400status.HTTP_400_BAD_REQUEST
包裝API視圖
REST framework 提供了兩個用于編寫API視圖的包裝器
-
是處理基于函數方法的API視圖的一個裝飾器@api_view
-
是基于類的API視圖APIView
這些包裝器提供了一些功能,例如:確定
Request
在視圖中能接收到執行個體對象,以及向
Response
對象添加内容以呈現給用戶端
并且提供了一些動作行為,例如:在适當的時候傳回
405 Method Not Allowed
響應,還有當通路
request.data
出現輸入格式錯誤時抛出
ParseError
異常
使用@api_view編寫API視圖
在上一篇文章中的項目案例中,修改
views.py
檔案,我們不再使用
JSONResponse
,是以用下面的代碼替換掉檔案的内容
from django.http import HttpResponse
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Snippet
from .serializers import SnippetSerializer
@api_view(['GET', 'POST'])
def snippet_list(request, format=None):
"""
列出所有代碼段,或建立新代碼段。
"""
if request.method == 'GET':
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
elif request.method == 'POST':
# data = JSONParser().parse(request)
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, format=None):
"""
檢索,更新或删除代碼段。
"""
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':
# data = JSONParser().parse(request)
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 HttpResponse(status=status.HTTP_204_NO_CONTENT)
- 現在的代碼看起來更加簡潔一點,其中還使用了命名的狀态碼,使響應的意義更加明顯
- 增加了
參數用于指定請求的類型,預設為format
,沒有指定的時候,會傳回它預設的視圖None
- 我們不再明确地将我們的請求或響應綁定到給定的内容類型,
可以處理request.data
請求,也可以處理其他格式的請求json
- 再修改
目錄下的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/<int:pk>', views.snippet_detail),
]
urlpatterns = format_suffix_patterns(urlpatterns) # 添加
- 進行測試:
http http://127.0.0.1:8000/snippets.json # 傳回 JSON 格式
http http://127.0.0.1:8000/snippets.api # 傳回 HTML API 格式
使用APIView編寫視圖
- APIView是基于類的API視圖
- 修改
檔案views.py
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class SnippetList(APIView):
"""
列出所有代碼段,或建立新代碼段。
"""
def get(self, request, format=None):
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
def post(self, request, format=None):
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)
class SnippetDetail(APIView):
"""
檢索,更新或删除代碼段。
"""
def get_object(self, pk):
try:
return Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
def put(self, request, pk, format=None):
snippet = self.get_object(pk)
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)
def delete(self, request, pk, format=None):
snippet = self.get_object(pk)
snippet.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
- 這與基于函數方法的API視圖還是很相似
- 接下來修改
目錄下的snippets
檔案urls.py
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
urlpatterns = [
path('snippets/', views.SnippetList.as_view()),
path('snippets/<int:pk>/', views.SnippetDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
- 測試方法與
一樣, 效果也是一緻的。@api_view