Django REST framework

本章內容;css

1. FBV與CBVhtml

  FBV: Function Base View前端

  CBV:Class Base Viewpython

 

 示例:git

 

from django.shortcuts import render, HttpResponse
from django.http import JsonResponse

# Create your views here.


def index(request):
    if request.method == "POST":
        print(request.POST)
        # 修改數據庫
        return HttpResponse("OK")
    return render(request, "index.html")

# CBV
from django import views


class Index(views.View):
    def get(self, request):
        return render(request, 'index.html')

    def post(self, request):
        print(request.POST)
        return HttpResponse("OK")

# def index2(request):
#     if request.method == "GET":
#         return render(request, "index.html")
#     print(request.POST)
#     # 修改數據庫
#     return JsonResponse("OK")


def ajax(request):
    return JsonResponse({"code": 0})
FBV

注意事項:github

 1.CBV定義必定要繼承django.views.viewajax

 2. 註冊路由的時候要寫 類名.as_view()數據庫

 3.具體原理是:dispatch()方法 中利用反射 找到每一個請求執行django

 1 from django import views
 2 
 3 
 4 class Index(views.View):
 5     def get(self, request):
 6         return render(request, 'index.html')
 7 
 8     def post(self, request):
 9         print(request.POST)
10         return HttpResponse("OK")
CBV格式寫法

一. 什麼是RESTful 

  • REST與技術無關,表明的是一種軟件架構風格,REST是Representational State Transfer簡稱,中文翻譯爲「表徵狀態轉移」
  • REST從資源的角度類審視整個網絡,它將分佈在網絡中某個節點的資源經過URL進行標識,客戶端應用經過URL來獲取資源的表徵,得到這些表導致這些應用轉變狀態
  • 全部的數據,不過是經過網絡獲取的仍是操做(增刪改查)的數據,都是資源,將一切數據視爲資源是REST區別與其餘架構風格的最基本屬性
  • 對於REST這種面向資源的架構風格,有人提出一種全新的結構理念,即:面向資源架構(ROA:Resource Oriented Architecture)

二. RESTful API設計

  • API與用戶的通訊協議,老是使用HTTPs協議
  • 域名 
    • https://api.example.com                         儘可能將API部署在專用域名(會存在跨域問題)
    • https://example.org/api/                        API很簡單
  • 版本
    • URL,如:https://api.example.com/v1/
    • 請求頭                                                  跨域時,引起發送屢次請求
  • 路徑,視網絡上任何東西都是資源,均使用名詞表示(可複數)
    • https://api.example.com/v1/zoos
    • https://api.example.com/v1/animals
    • https://api.example.com/v1/employees
  • method
    • GET      :從服務器取出資源(一項或多項)
    • POST    :在服務器新建一個資源
    • PUT      :在服務器更新資源(客戶端提供改變後的完整資源)
    • PATCH  :在服務器更新資源(客戶端提供改變的屬性)
    • DELETE :從服務器刪除資源
  • 過濾,經過在url上傳參的形式傳遞搜索條件
    • https://api.example.com/v1/zoos?limit=10:指定返回記錄的數量
    • https://api.example.com/v1/zoos?offset=10:指定返回記錄的開始位置
    • https://api.example.com/v1/zoos?page=2&per_page=100:指定第幾頁,以及每頁的記錄數
    • https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回結果按照哪一個屬性排序,以及排序順序
    • https://api.example.com/v1/zoos?animal_type_id=1:指定篩選條件

 狀態碼json

200 OK - [GET]:服務器成功返回用戶請求的數據,該操做是冪等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用戶新建或修改數據成功。
202 Accepted - [*]:表示一個請求已經進入後臺排隊(異步任務)
204 NO CONTENT - [DELETE]:用戶刪除數據成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用戶發出的請求有錯誤,服務器沒有進行新建或修改數據的操做,該操做是冪等的。
401 Unauthorized - [*]:表示用戶沒有權限(令牌、用戶名、密碼錯誤)。
403 Forbidden - [*] 表示用戶獲得受權(與401錯誤相對),可是訪問是被禁止的。
404 NOT FOUND - [*]:用戶發出的請求針對的是不存在的記錄,服務器沒有進行操做,該操做是冪等的。
406 Not Acceptable - [GET]:用戶請求的格式不可得(好比用戶請求JSON格式,可是隻有XML格式)。
410 Gone -[GET]:用戶請求的資源被永久刪除,且不會再獲得的。
422 Unprocesable entity - [POST/PUT/PATCH] 當建立一個對象時,發生一個驗證錯誤。
500 INTERNAL SERVER ERROR - [*]:服務器發生錯誤,用戶將沒法判斷髮出的請求是否成功。

更多看這裏:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

 

錯誤處理,狀態碼是4xx時,應返回錯誤信息,error當作key。

  {
    error: "Invalid API key"
  }

 

返回結果,針對不一樣操做,服務器向用戶返回的結果應該符合如下規範。

GET /collection:返回資源對象的列表(數組)
GET /collection/resource:返回單個資源對象
POST /collection:返回新生成的資源對象
PUT /collection/resource:返回完整的資源對象
PATCH /collection/resource:返回完整的資源對象
DELETE /collection/resource:返回一個空文檔

Hypermedia API,RESTful API最好作到Hypermedia,即返回結果中提供連接,連向其餘API方法,使得用戶不查文檔,也知道下一步應該作什麼。

1
2
3
4
5
6
{ "link" : {
   "rel" :    "collection https://www.example.com/zoos" ,
   "href" :   "https://api.example.com/zoos" ,
   "title" "List of zoos" ,
   "type" :   "application/vnd.yourformat+json"
}}

  

三. 基於Django實現

路由系統:

1
2
3
urlpatterns  =  [
     url(r '^users' , Users.as_view()),
]

CBV視圖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from  django.views  import  View
from  django.http  import  JsonResponse
 
class  Users(View):
     def  get( self , request,  * args,  * * kwargs):
         result  =  {
             'status' True ,
             'data' 'response data'
         }
         return  JsonResponse(result, status = 200 )
 
     def  post( self , request,  * args,  * * kwargs):
         result  =  {
             'status' True ,
             'data' 'response data'
         }
         return  JsonResponse(result, status = 200

 

 

四. 基於Django Rest Framework框架實現

基於django實現的API許多功能都須要咱們本身開發,這時候djangorestframework就給咱們提供了方便,直接基於它來返回數據,總之原理都是同樣的,就是給一個接口也就是url,讓前端的人去請求這個url去獲取數據,在頁面上顯示出來。這樣也就達到了先後端分離的效果。下面咱們來看看基於Django Rest Framework框架實現

1. 基本流程

實驗案例:新聞系統

實現方式一:

 1 from django.db import models
 2 
 3 # Create your models here.
 4 
 5 
 6 # 文章表
 7 class Article(models.Model):
 8     title = models.CharField(max_length=32)
 9     # 文章發佈時間
10     # auto_now每次更新的時候會把當前時間保存
11     create_time = models.DateField(auto_now_add=True)
12     # auto_now_add 第一次建立的時候把當前時間保存
13     update_time = models.DateField(auto_now=True)
14     # 文章的類型
15     type = models.SmallIntegerField(
16         choices=((1, "原創"), (2, "轉載")),
17         default=1
18     )
19     # 來源
20     school = models.ForeignKey(to='School', on_delete=models.CASCADE)
21     # 標籤
22     tag = models.ManyToManyField(to='Tag')
23 
24 
25 # 文章來源表
26 class School(models.Model):
27     name = models.CharField(max_length=16)
28 
29 
30 # 文章標籤表
31 class Tag(models.Model):
32     name = models.CharField(max_length=16)
models.py

執行命令:

migrate
makemigrations

插入數據庫數據

                                                

以上有了數據信息,而後進行json API接口的方式展現

 

1 from django.contrib import admin
2 from django.urls import path
3 from app01 import views
4 
5 urlpatterns = [
6     path('admin/', admin.site.urls),
7     path('article_list/',views.article_list),
8 ]
urls.py

 

 

 

from django.shortcuts import render,HttpResponse
from app01 import models
import json

# Create your views here.
def article_list(request):
    #去數據庫查詢全部的文章數據
    quest_set = models.Article.objects.all().values("id","title")  #values是字典,values_list是列表
    #序列化成json格式
    data = json.dumps(list(quest_set),ensure_ascii=False)
    #返回

    return HttpResponse(data)
views.py

 

注意:json只支持7種數據類型,ORM查詢出來的結果爲QuerySet類型,它是不支持的。

日期對象也是不支持的,須要轉換爲字符串。

啓動django項目,訪問URL: http://127.0.0.1/article_list/,所以每個時間,都要轉換爲字符串,太麻煩了。

 轉換方式:

 1 from django.shortcuts import render,HttpResponse
 2 from app01 import models
 3 import json
 4 
 5 # Create your views here.
 6 def article_list(request):
 7     #去數據庫查詢全部的文章數據
 8     quest_set = models.Article.objects.all().values("id","title","create_time")  #values是字典,values_list是列表
 9     #序列化成json格式
10 
11     #1.先把時間對象轉換成字符串格式
12     for i in quest_set:
13         i["create_time"] = i["create_time"].strftime('%Y-%m-%d')
14 
15     data = json.dumps(list(quest_set), ensure_ascii=False)
16     #返回
17     return HttpResponse(data)
views.py

 

第二個版本:JsonResponse

 JsonResponse 對象:

class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None,**kwargs)

這個類是HttpRespon的子類,它主要和父類的區別在於:

  • 1.它的默認Content-Type 被設置爲: application/json
  • 2.第一個參數,data應該是一個字典類型,當 safe 這個參數被設置爲:False ,那data能夠填入任何能被轉換爲JSON格式的對象,好比list, tuple, set。 默認的safe 參數是 True. 若是你傳入的data數據類型不是字典類型,那麼它就會拋出 TypeError的異常
  • 3.json_dumps_params參數是一個字典,它將調用json.dumps()方法並將字典中的參數傳入給該方法。

 

 1 from django.shortcuts import render,HttpResponse
 2 from django.http import JsonResponse
 3 from app01 import models
 4 import json
 5 
 6 # Create your views here.
 7 #第二種方式
 8 def article_list(request):
 9     #去數據庫查詢全部的文章數據,返回queryset,每個元素都是字典
10     query_set = models.Article.objects.all().values("id","title","create_time","type","school")
11     print(query_set)
12     for i in query_set:
13         print(i)
14 
15         #學校對象
16         school_obj = models.School.objects.filter(id=i['school']).first()
17         #學校id
18         id = school_obj.id
19         #學校的名字
20         name = school_obj.name
21         #修改字典,key爲school的值
22         i['school'] = {"id":id,"name":name}
23 
24         #返回json對象,safe=False表示任何能轉換爲json格式的對象
25         return JsonResponse(list(query_set),safe=False)
views.py

查看JsonResponse源代碼

def __init__(self, data, encoder=DjangoJSONEncoder, safe=True,
             json_dumps_params=None, **kwargs):
    if safe and not isinstance(data, dict):
        raise TypeError(
            'In order to allow non-dict objects to be serialized set the '
            'safe parameter to False.'
        )
    if json_dumps_params is None:
        json_dumps_params = {}
    kwargs.setdefault('content_type', 'application/json')
    data = json.dumps(data, cls=encoder, **json_dumps_params)
    super(JsonResponse, self).__init__(content=data, **kwargs)

注意:從上面的代碼中,能夠看出。針對查詢對應的學校信息,使用了for循環。它是一個外鍵字段,

那若是再查詢一個外鍵字段呢?再來一個for循環?代碼太冗長了!

第三個版本:serializers

serializers

 serializer 容許複雜數據(好比 querysets 和 model 實例)轉換成python數據類型,而後能夠更容易的轉換成 json 或 xml 等。同時,serializer也提供了反序列化功能,容許解析數據轉換成複雜數據類型。

中文文檔連接:

https://q1mi.github.io/Django-REST-framework-documentation/api-guide/serializers_zh/

聲明序列化器

class DBG(serializers.Serializer):  # 聲明序列化器
    id = serializers.IntegerField()
    title = serializers.CharField()
    create_time = serializers.DateField()
    type = serializers.IntegerField()
    school = serializers.CharField(source="school.name")

注意:source = "school.name" 表示school表中的name字段

 

可使用它來序列化和反序化與DBG對象相應的數據。

申明一個序列化看起來很是像申明一個form。咱們以前學習form組件時,將須要的字段類型都指定好了!  

聲明ModelSerializer

一般你會想要與Django模型相對應的序列化類。

ModelSerializer類可以讓你自動建立一個具備模型中相應字段的Serializer類。

這個ModelSerializer類和常規的Serializer類同樣,不一樣的是

  • 它根據模型自動生成一組字段。
  • 它自動生成序列化器的驗證器,好比unique_together驗證器。
  • 它默認簡單實現了.create()方法和.update()方法。

 

聲明一個ModelSerializer以下:

複製代碼
class CYM(serializers.ModelSerializer):
    type = serializers.CharField(source='get_type_display')

    class Meta:
        model = models.Article
        fields = "__all__"  # ("id", "title", "type")
        depth = 1  # 官方推薦不超過10層
複製代碼

默認狀況下,全部的模型的字段都將映射到序列化器上相應的字段。

模型中任何關聯字段好比外鍵都將映射到PrimaryKeyRelatedField字段。默認狀況下不包括反向關聯,除非像serializer relations文檔中規定的那樣顯示包含。

 

Model.get_FOO_display

查看官方文檔

https://docs.djangoproject.com/en/dev/ref/models/instances/#django.db.models.Model.get_FOO_display

對於具備選擇集的每一個字段,該對象將具備一個get_FOO_display()方法,其中FOO是該字段的名稱。 此方法返回字段的「可讀」值。

 

參數解釋:

source='get_type_display' 表獲取type字段中選擇集的值。

不懂?看一下models.py中的Article表,看這一段

# 文章的類型
    type = models.SmallIntegerField(
        choices=((1, "原創"), (2, "轉載")),
        default=1
    )

ORM是查詢表的數據,那麼這個type在真正存儲時,是1或2。

可是我想要獲得"原創"和"轉載",怎麼辦?那就須要我上面提到的get_type_display。

注意:type的變量名和字段名必須保持一致,那麼使用serializers後,結果集中type的值爲"原創"和"轉載",而不是1和2

 

model = models.Article  表示Article表

fields = "__all__"   表示全部字段,若是須要指定字段。能夠寫成這樣fields = ("id", "title", "type")

depth = 1   表示深度爲1層。有外鍵關聯時,才須要設置depth參數

由於Article表和School表,是一對多的關係,它們之間的關係只有一層。假設說:School表和另一個表(簡稱B表)有關係。Article表經過School表,要去查詢B表的數據,那麼層數就是2,以此類推!

 

使用ModelSerializer

def article_list(request):  # 查詢全部
    # 去數據庫查詢全部的文章數據
    query_set = models.Article.objects.all()
    xbg = CYM(query_set, many=True)
    print(xbg.data)
    # 返回
    return JsonResponse(xbg.data, safe=False)
複製代碼
def article_list(request):  # 查詢全部
    # 去數據庫查詢全部的文章數據
    query_set = models.Article.objects.all()
    xbg = CYM(query_set, many=True)
    print(xbg.data)
    # 返回
    return JsonResponse(xbg.data, safe=False)
複製代碼

參數解釋:

many=True  表示能序列化多個對象

什麼意思?article表有多條數據,每一條數據,就是一個對象。咱們須要查詢表的全部記錄,因此必須指定many=True。返回一條數據時,不須要指定many=True

 

獲取多條數據

views.py完整代碼以下:

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from app01 import models
import json
from rest_framework import serializers

# Create your views here.

class DBG(serializers.Serializer):  # 聲明序列化器
    id = serializers.IntegerField()
    title = serializers.CharField()
    create_time = serializers.DateField()
    type = serializers.IntegerField()
    school = serializers.CharField(source="school.name")


class CYM(serializers.ModelSerializer):  # 聲明ModelSerializer
    #
    type = serializers.CharField(source='get_type_display')

    class Meta:
        model = models.Article
        fields = "__all__"  # ("id", "title", "type")
        depth = 1  # 官方推薦不超過10層


def article_list(request):  # 查詢全部
    # 去數據庫查詢全部的文章數據
    query_set = models.Article.objects.all()
    xbg = CYM(query_set, many=True)
    print(xbg.data)
    # 返回
    return JsonResponse(xbg.data, safe=False)

 

 能夠看到type的值不是數字,而是選擇集中的值,它作了替換。是下面這一行,作了替換

 

type = serializers.CharField(source='get_type_display')

school的值,也能顯示相關聯的數據。

 

CYM是通用的,能夠多條,也能夠一條。

注意:多條的時候,須要加參數many=True。而一條,則不用!

 

獲取一條數據

修改urls.py,增長一個路徑

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^article_list/', views.article_list),
    url(r'article_detail/(\d+)', views.article_detail),
]

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^article_list/', views.article_list),
    url(r'article_detail/(\d+)', views.article_detail),
]

修改views.py,增長視圖函數

from django.shortcuts import render,HttpResponse
from django.http import JsonResponse
from app01 import models
import json
from rest_framework import serializers

# Create your views here.

class DBG(serializers.Serializer):  # 聲明序列化器
    id = serializers.IntegerField()
    title = serializers.CharField()
    create_time = serializers.DateField()
    type = serializers.IntegerField()
    school = serializers.CharField(source="school.name")


class CYM(serializers.ModelSerializer):  # 聲明ModelSerializer
    #
    type = serializers.CharField(source='get_type_display')

    class Meta:
        model = models.Article
        fields = "__all__"  # ("id", "title", "type")
        depth = 1  # 官方推薦不超過10層


def article_list(request):  # 查詢全部
    # 去數據庫查詢全部的文章數據
    query_set = models.Article.objects.all()
    xbg = CYM(query_set, many=True)
    print(xbg.data)
    # 返回
    return JsonResponse(xbg.data, safe=False)


def article_detail(request, id):  # 查詢單條數據
    article_obj = models.Article.objects.filter(id=id).first()
    xcym = CYM(article_obj)
    return JsonResponse(xcym.data)

 

刷新頁面,訪問url:  http://127.0.0.1:8000/article_detail/1

使用格式化工具,效果以下:

 

 

總結:

使用ORM對象轉換爲json對象時,推薦使用serializers

 

7、Postman使用

Postman一款很是流行的API調試工具。不只能夠調試簡單的css、html、腳本等簡單的網頁基本信息,它還可以發送任何類型的HTTP 請求 (GET, HEAD, POST, PUT..),附帶任何數量的參數+ headers。對於開發過程當中去調試接口,Postman確實足夠的簡單方便,並且功能強大。

官網地址:

www.getpostman.com

使用windows安裝以後,打開主程序,跳過登陸

 

 訪問文章列表 http://127.0.0.1:8000/article_list/

 

訪問文章詳情   http://127.0.0.1:8000/article_detail/1

 總結:

1. 使用Django 的視圖 本身序列化
    1. HttpResponse
    2. JsonResponse
    3. serializers

2. 使用Django REST Framework 框架的序列化工具類
    1. 安裝
        pip install djangorestframework
    2. 導入
        from rest_framework import serializers
    3. 使用
        class ArticleSerializer(serializers.Serializer):
            ...

外部python腳本調用django

有些狀況下,咱們須要使用python腳原本調用django,從而方便使用django提供的一些指令!

調試ORM

在django項目根目錄下建立文件test_orm.py,它和manage.py是同級的

import os

if __name__ == "__main__":
    # 設置django環境
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "about_drf.settings")
    import django
    django.setup()

    from app01 import models

    obj = models.Article.objects.filter(id=1).values()
    print(obj)

執行腳本,輸出以下:

<QuerySet [{'title': 'Python三年用不上', 'id': 1, 'school_id': 1, 'type': 1, 'update_time': datetime.date(2018, 7, 31), 'create_time': datetime.date(2018, 7, 31)}]>

 

清理過時session

若是用戶主動退出,session會自動清除,若是沒有退出就一直保留,記錄數愈來愈大,要定時清理沒用的session。

django中已經提供了這個方法,推薦把它加入到crontab中自動清理過時的session,防止session表記錄過大,影響訪問速度。

python E:\python_script\django框架\day15\about_drf\manage.py clearsessions
相關文章
相關標籤/搜索