django-rest-framework學習之路-8-Request請求與Response返回
django-rest-framework學習之路-8-Request請求與Response返回
request請求物件
我們先把許可權校驗等給取消,方便除錯
snippets/views.py內容變成了
from django.contrib.auth.models import User from rest_framework import renderers, viewsets, permissions from rest_framework.decorators import action from rest_framework.request import Request from rest_framework.response import Response from snippets.models import Snippet from snippets.permissions import IsOwnerOrReadOnly from snippets.serializers import SnippetSerializer, UserSerializer class UserViewSet(viewsets.ModelViewSet): """ 此檢視自動提供`list`和`detail`操作。 """ queryset = User.objects.all() serializer_class = UserSerializer class SnippetViewSet(viewsets.ModelViewSet): """ 此檢視自動提供`list`,`create`,`retrieve`,`update`和`destroy`操作。 另外我們還提供了一個額外的`highlight`操作。 """ queryset = Snippet.objects.all() serializer_class = SnippetSerializer permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly,) @action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer]) def highlight(self, request, *args, **kwargs): snippet = self.get_object() return Response(snippet.highlighted) def perform_create(self, serializer): serializer.save() def create(self, request: Request, *args, **kwargs): print("POST方法進入create函式") print(f"request dict:{request.__dict__}") print(f"data:{request.data}") print(f"query_params:{request.query_params}") print(f"parsers:{request.parsers}") print(f"user:{request.user}") print(f"auth:{request.auth}") print(f"method:{request.method}") print(f"content_type:{request.content_type}") print(f"stream:{request.stream}") return super().create(request, *args, **kwargs)
snippets/serializers.py內容變成了
from django.contrib.auth.models import User from rest_framework import serializers from snippets.models import Snippet class SnippetSerializer(serializers.ModelSerializer): owner = serializers.ReadOnlyField(source='owner.username') highlight = serializers.HyperlinkedIdentityField(view_name='snippet-highlight', format='html') class Meta: model = Snippet fields = ('url', 'id', 'highlight', 'owner', 'title', 'code', 'linenos', 'language', 'style') class UserSerializer(serializers.ModelSerializer): snippets = serializers.HyperlinkedRelatedField(many=True, view_name='snippet-detail', read_only=True) class Meta: model = User fields = ('url', 'id', 'username', 'snippets')
常用的屬性
.data屬性
request.data 返回請求正文的解析內容
- 它包括所有解析的內容, 包括 檔案或非檔案 輸入。
- 它支援解析除POST之外的HTTP方法的內容,這意味著你可以訪問PUT和PATCH請求的內容。
- 它支援REST framework靈活的請求解析,而不僅僅支援表單資料。 例如,你可以以與處理傳入表單資料相同的方式處理傳入的JSON資料
例如請求:
curl --location --request POST 'http://127.0.0.1:8000/snippets/snippets/' \
--header 'Host: 127.0.0.1' \
--header 'Content-Type: application/json' \
--data-raw '{
"title": "標題~~~",
"code": "程式碼~~~",
"linenos": false,
"language": "c",
"style": "friendly",
"A":1,
"B":"2"
}'
這樣可以獲取完整的body資料
.query_params屬性
獲取查詢路徑的請求引數,包括GET請求,POST請求
print(f"query_params:{request.query_params}")
例如
curl --location --request POST --X POST 'http://127.0.0.1:8000/snippets/snippets/?query1=1&query2=哈哈&query2=嘿嘿'
--header 'User-Agent: Apipost client Runtime/+https://www.apipost.cn/'
--header 'Host: 127.0.0.1'
--header 'Content-Type: application/json'
--data '{
"title": "標題~",~",
"code": "程式碼
"linenos": false,
"language": "c",
"style": "friendly",
"A": 1,
"B": "2"
}'
.method
request.method 返回請求的HTTP方法的 大寫 字串表示形式。
透明地支援基於瀏覽器的 PUT, PATCH 和 DELETE 表單。
.user
request.user 通常返回一個 django.contrib.auth.models.User 例項, 儘管該行為取決於所使用的的認證策略。
如果請求未認證則 request.user 的預設值為 django.contrib.auth.models.AnonymousUser的一個例項。
如果添加了認證,使用則顯示登入者
.auth
request.auth 返回任何其他身份驗證上下文。 request.auth 的確切行為取決於所使用的的認證策略,但它通常可以是請求被認證的token的例項。
如果請求未認證或者沒有其他上下文,則 request.auth 的預設值為 None.
以下是你通常並不需要訪問的屬性
.parsers屬性
APIView類或@api_view裝飾器將根據view中設定的parser_classes集合或基於DEFAULT_PARSER_CLASSES設定,確保此屬性自動設定為Parser例項列表。
你通常並不需要訪問這個屬性。
Note: 如果客戶端傳送格式錯誤的內容,則訪問request.data可能會引發ParseError。預設情況下REST framework的 APIView類或@api_view裝飾器將捕獲錯誤並返回400 Bad Request響應。
如果客戶端傳送具有無法解析的內容型別的請求,則會引發 UnsupportedMediaType 異常, 預設情況下會捕獲該異常並返回 415 Unsupported Media Type 響應。
.authenticators
APIView 類或 @api_view 裝飾器將根據在view中設定的 authentication_classes 或基於DEFAULT_AUTHENTICATORS 設定,確保此屬性自動設定為 Authentication 例項的列表。
你通常並不需要訪問此屬性。
.content_type
request.content_type 返回表示HTTP請求正文的媒體型別的字串物件,如果未提供媒體型別,則返回空字串。
你通常不需要直接訪問請求的內容型別,因為你通常將依賴於REST framework的預設請求解析行為。
如果你確實需要訪問請求的內容型別,你應該使用 .content_type 屬性,而不是使用 request.META.get('HTTP_CONTENT_TYPE'), 因為它為基於瀏覽器的非表單內容提供了透明的支援。
.stream
request.stream 返回一個表示請求主體內容的流。
你通常不需要直接訪問請求的內容型別,因為你通常將依賴於REST framework的預設請求解析行為。
Response返回物件
PS:(通常來說使用APIView類和@api_view函式即可,無需自己處理返回,除非自定義)
EST framework 通過提供一個 Response 類來支援 HTTP content negotiation,該類允許你返回可以呈現為多種內容型別的內容,具體取決於客戶端的請求。
Response 類是 Django中 SimpleTemplateResponse 類的一個子類。Response 物件用Python基本資料型別初始化。 然後REST framework 使用標準的HTTP content negotiation 來確定如何呈現最終的響應內容。
你並不需要一定是用 Response 類,你可以從你的檢視返回常規的 HttpResponse 或者 StreamingHttpResponse 物件。使用Response類只提供了一個可以呈現多種格式的更好的介面來返回 content-negotiated 的 Web API 響應。
除非由於某種原因你要對 REST framework 做大量的自定義,否則你應該始終對返回物件的views使用 APIView 類或者 @api_view 函式。這樣做可以確保檢視在返回之前能夠執行 content negotiation 並且為響應選擇適當的渲染器。
屬性
.data
Request 物件的未渲染內容。
.status_code
HTTP 響應的數字狀態嗎。
.content
response的呈現內容。 .render() 方法必須先呼叫才能訪問 .content 。
.template_name
template_name 只有在使用 HTMLRenderer 或者其他自定義模板作為response的渲染器時才需要提供該屬性。
.accepted_renderer
將用於呈現response的render例項。
自動通過 APIView 或者 @api_view 在view返回response之前設定。
.accepted_media_type
由 content negotiation 階段選擇的媒體型別。
自動通過 APIView 或者 @api_view 在view返回response之前設定。
.renderer_context
一個將傳遞給渲染器的.render()方法的附加上下文資訊字典。
自動通過 APIView 或者 @api_view 在view返回response之前設定。
標準的HttpResponse 屬性
Response 類擴充套件了 SimpleTemplateResponse,並且所有常用的屬性和方法都是提供的。比如你可以使用標準的方法設定response的header資訊:
response = Response()
response['Cache-Control'] = 'no-cache'
.render()
Signature: .render()
和其他的 TemplateResponse 一樣,呼叫該方法將response的序列化資料呈現為最終的response內容。 當 .render() 被呼叫時, response的內容將被設定成在 accepted_renderer例項上呼叫 .render(data, accepted_media_type, renderer_context) 方法返回的結果。
你通常並不需要自己呼叫 .render() ,因為它是由Django的標準響應週期來處理的。