1. 程式人生 > 其它 >django-rest-framework(更新中)

django-rest-framework(更新中)

@

目錄

(三十六)Web應用模式

在Web開發中,有兩種模式:

  1. 前後端分離

#前後端分離:  只專注於後端,返回json格式資料
  1. 前後端不分離

# 前後端混合開發(前後端不分離)  返回的是HTML的內容,需要寫模板

# 動態頁面(查資料庫),靜態頁面(一個靜止的html)

# 頁面靜態化

(三十七)API介面

通過網路,規定了前後端資訊互動的url連線,也就是前後端資訊互動的媒介

(三十八)Restful規範

REST全稱是Representational State Transfer,中文意思是表述(編者注:通常譯為表徵性狀態轉移)。它首次出現在2000年Roy Fielding的博士論文中

RESTFUL是一種定義Web API介面的設計風格,尤其適合前後端分離的應用模式中。

這種風格的理念認為後端開發任務就是提供資料的,對外提供的是資料資源訪問的介面,所以在定義介面時,客戶端訪問的URL路徑就表示這種需要操作的資料資源

事實上,我們可以使用任何一種框架都可以實現符合RESTFUL規範的API介面
  1. 資料的安全保障
url連結一般都採用https協議進行傳輸,注:採用Https協議,可以提高資料		互動過程中的安全性
  1. 介面的特徵表現
     -用api關鍵字標識介面url:
            -[https://api.baidu.com](https://api.baidu.com/)
            -https://www.baidu.com/api
        注:看到api欄位,就代表該請求url連結是完成前後端資料互動的
 
 
  1. 多版本共存
-在url連結中標識資料版本
-https://api.baidu.com/v1
-https://api.baidu.com/v2
注:url連結中的v1,v2,就是不同資料版本的提現,(只有在一種資料資源有多版本情況下)
  1. 資料即資源
介面作為前後端互動的媒介其互動的資料又被叫做資源,推薦使用名詞或者名詞的複數形式,對於某些特殊介面,我們可以使用動詞(api/books api/login)
    	- 介面一般都是前後端資料的互動,互動的資料稱之為資源
        	- https://api.baidu.com/users
            - https://api.baidu.com/books
  1. **資源操作由請求方式決定 ** (method)
資源的操作我們直接通過提交的請求方式來決定(get、post、put/patch、delete)
 - 操作資源一般都涉及到增刪改查,以下請求方式來標識增刪改查動作
        https://api.baidu.com/books     -get請求:獲取所有書
        https://api.baidu.com/books/1   -get請求:獲取主鍵為1 的書
        https://api.baidu.com/books     -post請求: 新增一本書
        https://api.baidu.com/books/1   -put請求:整體修改主鍵為1的書
        https://api.baidu.com/books/1   -patch請求:區域性修改主鍵為1 的書
        https://api.baidu.com/books/1   -delete請求:刪除主鍵為1 的書
  1. 過濾
我們可以再url上傳參的形式傳遞搜尋條件
    https://api.example.com/v1/people?limit=10  :指定返回記錄的數量
    https://api.example.com/v1/people?offset=10 :指定返回記錄的開始位置
    https://api.example.com/v1/people?page=2&per_page=100 :指定第幾頁,以及每頁的記錄數
    https://api.example.com/v1/people?sortby=name&order=asc:指定返回結果按照哪個屬性排序,以及排序順序
    https://api.example.com/v1/people?animal_type_id=1 :指定篩選條件
  1. 響應狀態碼
# 正常響應
    200(正常請求)、
    201(建立成功)、
# 重定向響應
    301(永久重定向)、
    302(臨時重定向)、
# 客戶端異常
    403(請求無許可權)、
    404(請求路徑不存在)、
    405(請求方法不存在)、
# 服務端異常
	500(伺服器異常)、

  1. 錯誤處理
應當返回錯誤資訊   error當作key

{
    error:'無許可權操作'
}
  1. 返回結果
根據不同的請求以及請求得到的資料, 服務端返回不同的結果
	GET /collection:返回資源物件的列表(陣列)
    GET /collection/resource:返回單個資源物件
    POST /collection:返回新生成的資源物件
    PUT /collection/resource:返回完整的資源物件
    PATCH /collection/resource:返回完成的資源物件
    DELETE /collection/resource:返回一個空文件
    
  1. 需要url請求的資源需要訪問資源的請求連結
	# Hypermedia API ,RESTFUL API最好做到Hypermedia,即返回結果中提供連結,連向其他API方法,使得使用者不查文件,也知道下一步應該做什麼
    {
        "status":0,
        "msg":"OK",
        "results":[
            {
                "name":"肯德基",
                "img":"https://image.baidu.com/ftc/001.png"
            }
            ........
        ]  
    }

(三十九)drf安裝和簡單使用

1、安裝

#安裝
pip install djangorestframework   

2、使用

1.settings.py中
    INSTALLED_APPS = [
        'rest_framework'
    ]
2.在models.py中寫表模型
    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=8, decimal_places=2)
        author = models.CharField(max_length=32)
        
3. 新建一個序列化類 (新建一個py檔名字隨意)
	from rest_framework.serializers import ModelSerializer
    from App.models import Book


    class BookModelSerializer(ModelSerializer):
        class Meta:
            model = Book
            fields = '__all__'

4.檢視中寫檢視類(CBV)
	from rest_framework.viewsets import ModelViewSet
    from .models import Book
    from .ser import BookModelSerializer     #ser指的是第三步中建立的py檔案

    class BooksViewSet(ModelViewSet):
        queryset = Book.objects.all()
        serializer_class = BookModelSerializer

5.寫路由關係
    from django.contrib import admin
    from django.urls import path
    from rest_framework.routers import DefaultRouter
    from App import views

    router = DefaultRouter()  # 可以處理檢視的路由器
    router.register('book', views.BooksViewSet)  # 向路由中註冊檢視集

    # 將路由器中的所有路由資訊追溯到django的路由列表中
    urlpatterns = [
        path('admin/', admin.site.urls),
    ]
    # 兩個列表相加
    urlpatterns += router.urls  # router.urls是一個列表

6. 資料遷移
	python manage.py makemigrations
    python manage.py migrate
7.啟動專案,測試

啟動專案程式

3、postman測試

postman中測試,postman中最後要加/,瀏覽器會自動重定向,但postman不會,所以在postman中最後要加/

  • 查資料
  • 刪資料

2刪除後,就找不到資料

刪除2資料後,再檢視所有資料

  • 修改資料

修改完後,再次查詢所有

  • 增加資料

增加後再次檢視所有資料

(四十)原始碼分析

cbv

ModelViewSet繼承與View (djanog原生View)
path('books/',views.Books.as_view())#在這個地方應該寫函式記憶體地址,views.Books.as_view()執行完,是個函式記憶體地址,as_view是一個類方法,類直接來呼叫,會把類自動傳入
放入了一個view的記憶體地址,(View--》as_view--》內層函式)

class Books(View):
    # 只能接收get請求
    http_method_names = ['get']
    def get(self, request):
        print(self.request)
        return HttpResponse('ok')

"""原始碼分析"""

#請求來了,如果路徑匹配,會執行,函式記憶體地址(request)
def view(request, *args, **kwargs):
    #request是當次請求的request
    self = cls(**initkwargs)
    self.setup(request, *args, **kwargs)
    if not hasattr(self, 'request'): #例項化得到一個物件 Book物件
        raise AttributeError(
            "%s instance has no 'request' attribute. Did you override "
            "setup() and forget to call super()?" % cls.__name__
        )
        return self.dispatch(request, *args, **kwargs)
    
    
    
    
def dispatch(self, request, *args, **kwargs):
    #request就是當次請求的request  selef是Book物件
    if request.method.lower() in self.http_method_names:
        #handle是自己寫的Book類的get方法的記憶體地址
        handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
    else:
        handler = self.http_method_not_allowed
        return handler(request, *args, **kwargs) #執行get(request)   

APIView原始碼分析

#urls.py
path('booksapiview/', views.BooksAPIView.as_view()),在這個地方應該寫函式記憶體地址

#views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request

class BooksAPIView(APIView):
    def get(self, request):
        #request已經不是原生的django的request了,是drf自己定義的request物件
        print(self.request)
        return HttpResponse('ok')
    
"""原始碼分析"""

#APIView的as_view方法(類的繫結方法)
@classmethod
def as_view(cls, **initkwargs):
    view = super().as_view(**initkwargs)#呼叫父類(View)的as_view方法,
    view.cls = cls
    view.initkwargs = initkwargs
    #以後所有的請求都沒有csrf認證了,只要繼承了APIV i額外,就沒有csrf認證了
    return csrf_exempt(view)

#請求來了,路由匹配上,會執行view(request),呼叫了self.dispatch(),會執行apiview的self.dispatch()

#APIView的dispatch方法
 def dispatch(self, request, *args, **kwargs):

        self.args = args
        self.kwargs = kwargs
        #請求模組(解析模組)
        # self.initialize_request(request, *args, **kwargs)   這裡的request是當次請求的request
        #request= self.initialize_request  這裡的request是一個新的request物件
        #重新包裝成一個request物件,以後再用的request物件,就是新的request物件
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        try:
            #
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
			#響應模組
            response = handler(request, *args, **kwargs)

        except Exception as exc:
            #異常模組
            response = self.handle_exception(exc)
		#渲染模組
        self.response = self.finalize_response(request, response, *args, **kwargs)
        return self.response

補充:

一切皆物件

def foo(a, b):
    return a + b

foo.name = 'zhao'

print(foo(1, 3))
print(foo.name)

區域性禁用csrf

#檢視函式中加裝飾器@csrf_exempt

#csrf_exempt(view)和在檢視函式上加裝飾器是一摸一樣的
from django.views.decorators.csrf import csrf_exempt

urlpatterns = [
    path('test/',csrf_exempt(views.test))#也是禁用csrf認證
]

drf的Request類

from rest_framework.request import Request
#只要繼承了APIView,檢視中的request物件,都是新的,也就是上面這個request的物件,

#老的request在新的request._request裡

#以後使用request物件,就像使用之前的request是一摸一樣的(因為重寫了__getattr__方法)

 def __getattr__(self, attr):
        try:
            return getattr(self._request, attr) #通過反射,取原生的request物件,取出屬性和方法
        except AttributeError:
            return self.__getattribute__(attr)
        
        
#request.data 感覺是資料屬性,其實是個方法,@property修飾了
它是一個欄位,post請求不管使用社麼編碼,傳過來的資料,都在request.data中