1. 程式人生 > 其它 >django-rest-framework學習之路-8-Request請求與Response返回

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的標準響應週期來處理的。