Django REST framework---請求和響應

Django REST framework---請求和響應html


 【Request對象】前端

 

概念:python

  平時咱們在寫Django的視圖函數的時候,都會帶上一個request參數,這樣就能處理平時搭建網站時,瀏覽器訪問網頁時發出的常規的HttpRequest。可是如今咱們導入了django-rest-framework,它可以對request進行拓展,而且提供更靈活的請求解析。django

區別:json

  request.POST只能處理前端發起的POST請求,只能處理表單提交的數據。而request.data能夠處理任意數據,而不僅僅是前端提交的表單數據,可用於post, put, patch請求。api

實例:瀏覽器

  

request.POST  # Only handles form data.  Only works for 'POST' method.
request.data  # Handles arbitrary data.  Works for 'POST', 'PUT' and 'PATCH' methods.

 

 

 

【Response對象】服務器

 

說明:app

  和request對象同樣,django-rest-framework也對其進行了很實用的拓展,在我上一篇文章的snippets/views.py中,咱們導入了JsonResponse用於返回json格式的響應,在視圖函數中是這樣的:框架

舉例:

@csrf_exempt
def snippet_list(request):
    """
    List all code snippets, or create a new snippet.
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return JsonResponse(serializer.data, safe=False)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = SnippetSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)

 

 

【狀態碼】

 

說明:  

  咱們知道發送http請求時會返回各類各樣的狀態嗎,可是都是簡單的數字,好比200、404等,這些純數字標識符有時候可能不夠明確或者客戶端在使用的時候不清楚錯誤信息甚至是沒注意看不到,因此django-rest-framework也對此進行了優化,狀態碼會是HTTP_400_BAD_REQUEST、HTTP_404_NOT_FOUND這種,極大的提升可讀性

 

 

【包裝API視圖】

  

REST框架提供了兩個可用於編寫API視圖的包裝器。

  • @api_view裝飾器用於處理基於函數的視圖
  • APIView類用在基於視圖的類上

這些包裝提供了一些功能,讓咱們省去不少工做。好比說確保你在視圖中收到Request對象或在你的Response對象中添加上下文,這樣就能實現內容通訊。

另外裝飾器能夠在接收到輸入錯誤的request.data時拋出ParseError異常,或者在適當的時候返回405 Method Not Allowed狀態碼。

緊接着咱們再次的重構views.py,當使用裝飾器的時候就不須要使用JOSNresponse

@api_view(['GET', 'POST'])
def snippet_list(request):
    """
    List all code snippets, or create a new snippet.
    """
    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):
    """
    Retrieve, update or delete a code snippet.
    """
    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)

以上就是對原有的常規的Django視圖函數的改進。

總結一下就是處理request提交過來的數據不須要必定是json格式的數據,返回的響應也不須要必定是json數據,也能夠是通過渲染的HTML頁面。稍後就會示範使用。

 

 

【向URL添加可選格式後綴】

既然上面已經說了返回給客戶端的Response但是json或者是HTML等格式的內容,那麼用戶在使用的時候是如何指定返回哪一種格式的內容呢,那就是在URL的最後加上後綴。好比http://127.0.0.1:8000/snippets.json,這樣就是用戶本身指定了返回json格式的Response,而不是咱們在後臺指定返回固定的格式。

只需對咱們的程序稍加改進就能夠了,在兩個視圖函數添加關鍵詞參數format:

def snippet_list(request, format=None):
-------------------------------------------------------
def snippet_detail(request, pk, format=None):

接下來就是更改咱們urls.py文件增長格式後綴的一種的模式

from django.conf.urls import url
from . import views
from rest_framework.urlpatterns import format_suffix_patterns

urlpatterns = [
    url(r'^snippets/$', views.snippet_list),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.snippet_detail),
]

urlpatterns = format_suffix_patterns(urlpatterns)

 

 

 

 對咱們上述的Api進行測試

經過啓動服務器的方式

 

還能夠在終端下使用http

lee@lee:~/PycharmProjects/Djdemo$ source venv/bin/activate
(venv) lee@lee:~/PycharmProjects/Djdemo$ http http://127.0.0.1:8000/snippets/
HTTP/1.1 200 OK
Allow: OPTIONS, GET, POST
Content-Length: 317
Content-Type: application/json
Date: Mon, 06 Aug 2018 15:29:29 GMT
Server: WSGIServer/0.2 CPython/3.5.2
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

[
    {
        "code": "foo = \"bar\"\n",
        "id": 3,
        "language": "python",
        "linenos": false,
        "style": "friendly",
        "title": ""
    },
    {
        "code": "print \"hello, world\"\n",
        "id": 4,
        "language": "python",
        "linenos": false,
        "style": "friendly",
        "title": ""
    },
    {
        "code": "print \"hello, world\"",
        "id": 5,
        "language": "python",
        "linenos": false,
        "style": "friendly",
        "title": ""
    }
]

咱們能夠經過使用Accept標頭來控制咱們獲得的響應的格式

http http://127.0.0.1:8000/snippets/ Accept:application/json  # Request JSON
http http://127.0.0.1:8000/snippets/ Accept:text/html         # Request HTML

或者經過附加格式後綴:

http http://127.0.0.1:8000/snippets.json  # JSON suffix
http http://127.0.0.1:8000/snippets.api   # Browsable API suffix

一樣,咱們可使用Content-Type標頭控制咱們發送的請求的格式

(venv) lee@lee:~/PycharmProjects/Djdemo$ http --form POST http://127.0.0.1:8000/snippets/ code="print 123"
HTTP/1.1 201 Created
Allow: OPTIONS, GET, POST
Content-Length: 93
Content-Type: application/json
Date: Mon, 06 Aug 2018 15:36:11 GMT
Server: WSGIServer/0.2 CPython/3.5.2
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

{
    "code": "print 123",
    "id": 6,
    "language": "python",
    "linenos": false,
    "style": "friendly",
    "title": ""
}

--------------

(venv) lee@lee:~/PycharmProjects/Djdemo$ http --json POST http://127.0.0.1:8000/snippets/ code="print 456"
HTTP/1.1 201 Created
Allow: OPTIONS, GET, POST
Content-Length: 93
Content-Type: application/json
Date: Mon, 06 Aug 2018 15:36:50 GMT
Server: WSGIServer/0.2 CPython/3.5.2
Vary: Accept, Cookie
X-Frame-Options: SAMEORIGIN

{
    "code": "print 456",
    "id": 7,
    "language": "python",
    "linenos": false,
    "style": "friendly",
    "title": ""
}

 

 

 

若是報錯:請參照 https://www.cnblogs.com/youleng/p/9117920.html

--------將繼續完善

相關文章
相關標籤/搜索