drf之框架基礎

yq055783發表於2020-06-16

(一)drf基礎

全稱:django-rest framework

介面:什麼是介面、restful介面規範(協議)

CBV(基於FBV的基礎上形成)、CBV生命週期原始碼----基於restful規範下的CBV介面

請求生命週期:請求元件、解析元件、響應元件

序列化元件(序列化、反序列化簡單來說就是物件轉為字串、字串轉為物件,目的是為傳輸資料(傳給別的語言或者儲存))

三大認證(重中之重):認證(使用者是否合法)、許可權(管理員、普通使用者)、頻率(次數過多限制)

其他元件(過濾、篩選、排序、分頁、路由)

 

1.介面

概念:聯絡兩個物質的媒介,完成資訊的互動。在web程式中,聯絡前臺頁面後臺資料庫的媒介。

web介面組成:

url:長得像返回資料的url連結。如api.baidu.map/search

www.baidu.com不叫介面,叫url連結,訪問只能拿到主頁。api.baidu.map/search是介面,返回的是json資料)

請求引數:前臺按照指定的key提供資料給後臺。(必須是給定的,這樣後臺才能以此提取資料再到資料庫查詢返回)

響應資料:後臺與資料庫互動後,將資料反饋給前臺。

因此,介面就是帶著請求引數訪問能夠得到響應資料的url連結。

介面 = url + 請求引數 + 響應資料

 

 

2.restful介面規範

介面規範:不同後臺語言,使用同樣的介面返回同樣的資料。

如何寫介面:要寫url和響應資料。如果將請求引數也加上,就是在寫介面文件。

 

兩大部分:

1url

1)用api關鍵字標識介面url。方式1api.baidu.com;方式2:www.baudu.com/api

2)介面資料安全性決定優先選用https協議

3)如果一個介面有多版本存在,需要在url中標識體現。如下的v1v2

api.baidu.com/v1/....  api.baidu.com/v2/....

4)操作中的資料稱為資源,在url中資源一般採用複數形式,一個介面可以概括對該資源的多種操作方式。(一個url對應一個類,類裡面可以有多個請求方法)

可以對操作隱藏,並且複用性更強(寫動作了,只能適用這一個動作,不寫其他動作都可以用)如api.baidu.com/books    api.baidu.com/books/(pk)

5)請求方式有多種,用一個url處理如何讓保證不混亂------通過不同的請求方式標識不同操作資源的方式

/books      get     獲取所有

/books post   增加一個(多個)

/books/(pk) delete 刪除一個

/books/(pk)  put 整體更新一個  #改一個使用者

/books/(pk)  patch 區域性更新一個 #改一個使用者的密碼

 

6)資源往往涉及資料的各種操作方式:篩選、排序、限制

api.baidu.com/books/?search=寶馬&ordering=-price&limit=3

 

2)響應資料

1http請求的響應會有響應狀態碼,介面用來返回操作的資源資料,也有自己運算元據結果的資源狀態碼status 0代表操作資源成功,1代表操作失敗,2代表操作成功,但沒匹配結果)

注:資源狀態碼和http狀態碼不一樣,為前後臺的約定

2)資源狀態碼的文字提示。

status ok “賬號有誤或者密碼有誤”

3)資源本身

results

:刪除資源成功不做任何資料返回(只返回空字串,連狀態碼、狀態資訊都不返回)

4)不能直接返回的資源(子資源、圖片、視訊等資源),返回該資源的url連結。

 

https://api.baidu.com/v1/books?limit=3
get|post|delete|put|patch   
{
  “status” : 0,
  “msg” : “ok”,
  “results”: [
{
  “title”: “三國”,
  “price”: 78,
  “img”: “https://.....”   
    }
  ]
}

 

3.django流程

1)專案準備:

 

1.分發路由

在專案資料夾的urls複製一份到應用資料夾中。然後在專案資料夾的urls分發路由給app:匯入include,然後url(r'^api/', include('api.urls'))。再在app資料夾的urls.py中分發路由給CBV

2.檢視

在應用中分發路由前,先寫類檢視

from django.http import JsonResponse
from django.views import View

class Book(View):

    def get(self, request, *args, **kwargs):
        return JsonResponse('get ok', safe=False)

    def post(self, request, *args, **kwargs):
        return JsonResponse('get ok', safe=False)   #safe預設為true,要返回字典。不是字典否則拋異常。

 

3.在應用urls下分發路由

from django.conf.urls import url
from . import views    #注意在應用中匯入檢視都是.   從當前應用中匯入

urlpatterns = [
    url(r'^books/', views.Book.as_view()),
]

 

4.定義模型類

1models.py中定義類

from django.db import models

class Book(models.Model):

    title = models.CharField(max_length=64)
    price = models.DecimalField(max_digits=5, decimal_places=2) #整數、小數位

    class Meta:    #巢狀類(給上級類新增功能或指定標準)
        
       db_table = 'book'    #自定義資料庫表名
        verbose_name = "book"   #給模型起個可讀的名字,預設是複數
        verbose_name_plural = verbose_name   #取消上面的複數

    def __str__(self):      #顯示的內容
        return '<<%s>>' % self.title    

 

 

   (2)資料庫遷移

進入djangoshell環境中:Tools----> run manage.py task

shell環境中生成遷移檔案:makemigrations。然後遷移:migrate

 

5.生成admin

1)在amin.py中註冊並且匯入模型

from django.contrib import admin
port models

admin.site.register(models.Book)

 

2)建立使用者

shell環境中:createsuper建立超級使用者,然後輸入使用者密碼(郵箱不用)

 

 

 2CBV的請求生命週期

請求如何到CBV下的getpost

a.請求過來,專案檔案中路由分發給應用api的路由

b.應用分發路由走as_view函式。

views.Book.as_view()  儲存一系列資料(requestargs**kwargs等)給Book物件,然後都給dispatch進行路由分發。

dispatch乾的事:判斷請求方式是否支援,然後返回(通過getattr)支援的這些請求方法(getpost等,在檢視中自定義getpost的返回值)的結果。

c.通過dispatch就執行了CBV下請求方式的結果,返回結果

 

 

4.django原生的介面、序列化

  六大基礎介面:獲取一個、獲取所有、增加一個、刪除一個、整體更新一個、區域性更新一個

 十大介面:6大基礎、群增、群刪、整體群改、區域性群改

 

1.在應用的urls.py下分發路由

url(r'^books/$', views.Book.as_view()),   #必須要加$,否則後面匹配不到

url(r'^books/(?P<pk>.*)/$', views.Book.as_view()),有名分組

在檢視函式中通過kwargs.get(pk)取到匹配的值

 

2.views.py裡寫邏輯

class Book(View):

 

    def get(self, request, *args, **kwargs):

        pk = kwargs.get('pk')  #獲取引數

        if not pk:  #群查介面

            #運算元據庫

            book_obj_list = models.Book.objects.all()

            #序列化過程

            book_list = []

            for obj in book_obj_list:   #將查到的物件序列化

                dic = {}

                dic['title'] = obj.title

                dic['price'] = obj.price

                book_list.append(dic)

            return JsonResponse({

                'status' : 0,

                "msg" : "ok",

                "results": book_list,

            }, json_dumps_params={'ensure_ascii':False})

        else:    #單查介面

            book_dic = models.Book.objects.filter(pk=pk).values(

                'title', 'price').first()

            if book_dic:

                return JsonResponse({

                    'status': 0,

                    "msg": "ok",

                    "results": book_dic,

                }, json_dumps_params={'ensure_ascii': False})

 

            return JsonResponse({

                'status': 2,

                "msg": "no results",

            }, json_dumps_params={'ensure_ascii': False})

 

 

    def post(self, request, *args, **kwargs):

        #前臺通過urlencoded方式提交資料

        try:

            book_obj = models.Book.objects.create(**request.POST.dict()) #create建立物件。將request.POST中存放的提交的關鍵詞引數轉化為字典以**方式傳進去。沒傳引數,這邊會報錯。

            if book_obj:

                return JsonResponse({

                'status': 0,

                "msg": "ok",

                “results”: {‘title’:book_obj.title, “price”:book_obj.price}

            }, json_dumps_params={'ensure_ascii': False})

        except:    #健壯性

            return JsonResponse({

                'status': 1,

                "msg": "wrong params",

            }, json_dumps_params={'ensure_ascii': False})

        return JsonResponse({    #可能運算元據庫失敗了

                'status': 2,

                "msg": "created failed",

            }, json_dumps_params={'ensure_ascii': False})

           

  

JsonResponse返回時,中文會變成unicode,要加json_dumps_params={'ensure_ascii':False}選項。但在linux環境下的火狐瀏覽器,加了是亂碼。

 

filter返回queryset物件,物件裡是個列表(表名:物件資訊(有自定義str就是自定義的資訊))。first取裡第一個物件(相當於print(第一個物件)values展示對應的物件裡的值

<QuerySet [<Book: <<三國演義>>>]>                   #直接.filter

<<三國演義>>                                    #.first()

<QuerySet [{'title': '三國演義', 'price': Decimal('56.00')}]>  #.values('title','price')

{'title': '三國演義', 'price': Decimal('56.00')}             #.values.first()  是個字典

 

 上面序列化的工作很麻煩。drf就是為了方便序列化的。

 

postman可以完成不同方式的請求:getpostput

postman傳送資料包有三種方式:form-dataurlencodedjson. 原生djangourlencoded資料提交相容。

 

相關文章