溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

發(fā)布時(shí)間:2020-10-07 01:53:08 來(lái)源:腳本之家 閱讀:138 作者:蔚藍(lán)的藍(lán) 欄目:開(kāi)發(fā)技術(shù)

django rest framework 官網(wǎng)

在學(xué)習(xí)django rest framework(下面簡(jiǎn)稱drf)之前需要知道

  • 對(duì)RESTful API設(shè)計(jì)有一定了解
  • 對(duì)django框架有一定認(rèn)識(shí),本身drf就是基于django做的
  • 對(duì)python面向?qū)ο缶幊逃辛私猓╠rf會(huì)對(duì)一些原生的django類做封裝)

一、前言

在學(xué)習(xí)drf之前的時(shí)候,先簡(jiǎn)單說(shuō)一下需要的預(yù)備知識(shí)。在django中,路由匹配之后,會(huì)進(jìn)行路由分發(fā),這個(gè)時(shí)候會(huì)有兩種選擇模式的選擇。也就是FBVCBV。

1、FBV

fbv就是在url中一個(gè)路徑對(duì)應(yīng)一個(gè)函數(shù)

urlpatterns = [
  url(r'^admin/', admin.site.urls),
  url(r'^index/', views.index)
]

在視圖函數(shù)中

def index(request):
  return render(request, 'index.html')

2、CBV

cbv就是在url中一個(gè)路徑對(duì)應(yīng)一個(gè)類,drf主要使用CBV

urlpatterns = [
  url(r'^admin/', admin.site.urls),
  url(r'^index/', views.IndexView.as_view())   # 執(zhí)行類后面的as_view()方法,是父類里面的方法
]

在視圖函數(shù)中

from django.views import View


class IndexView(View):
 
  # 以get形式訪問(wèn)會(huì)執(zhí)行g(shù)et函數(shù),一般情況下獲取數(shù)據(jù)
  def get(self, *args, **kwargs): 
    return HttpResponse('666')
   
  # 以post形式訪問(wèn)的話會(huì)執(zhí)行post函數(shù),一般情況下發(fā)送數(shù)據(jù)
  def post(self, *args, **kwargs): 
    return HttpResponse('999')

我們?cè)诼酚善ヅ涞臅r(shí)候看到url(r'^index/', views.IndexView.as_view()),那這個(gè)as_view()是什么,既然我們?cè)谝晥D類中沒(méi)有定義這個(gè)as_view()方法,就應(yīng)該到父類(也就是IndexView的父類View)中看一下View。以下是django源碼,路徑是\django\views\generic\base.py,

class View:

  http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'] # 支持的各種http方法

  def __init__(self, **kwargs):
     pass

  @classonlymethod
  def as_view(cls, **initkwargs): # url路由匹配進(jìn)入as_view方法
    def view(request, *args, **kwargs):
      return self.dispatch(request, *args, **kwargs) # 返回dispath方法
    return view

  def dispatch(self, request, *args, **kwargs): # dispath方法是drf的關(guān)鍵,dispath方法會(huì)通過(guò)反射,通過(guò)請(qǐng)求的方法,分發(fā)到各個(gè)視圖類的方法中
    pass

3、django的請(qǐng)求周期

因此根據(jù)CBV和FBVdjango的生命周期可以又兩類

FBV:請(qǐng)求通過(guò)uwsgi網(wǎng)關(guān),中間件,然后進(jìn)入路由匹配,進(jìn)入視圖函數(shù),連接數(shù)據(jù)庫(kù)ORM操作,模板渲染,返回經(jīng)過(guò)中間件,最終交給瀏覽器response字符串。

CBV:請(qǐng)求通過(guò)uwsgi網(wǎng)關(guān),中間件,然后進(jìn)入路由匹配,這里就與FBV有區(qū)別了,因?yàn)椴辉偈窃噲D函數(shù)而是視圖類,說(shuō)的詳細(xì)一點(diǎn),先經(jīng)過(guò)父類View的dispath方法,進(jìn)行請(qǐng)求方法的判斷,在分發(fā)到視圖類的方法,連接數(shù)據(jù)庫(kù)ORM操作,模板渲染,返回經(jīng)過(guò)中間件,最終交給瀏覽器response字符串。

而再drf中主要使用CBV,生命周期就變成了如下

請(qǐng)求通過(guò)uwsgi網(wǎng)關(guān),中間件,然后進(jìn)入路由匹配,這里就有區(qū)別了,先經(jīng)過(guò)drf中APIView類中的dispath方法(這里假定視圖類沒(méi)有重寫APIView中的dispath方法),在dispath中對(duì)request請(qǐng)求進(jìn)行封裝,反射回到視圖類,連接數(shù)據(jù)庫(kù)ORM操作,模板渲染,返回經(jīng)過(guò)中間件,最終交給瀏覽器響應(yīng)字符串。

4、面向?qū)ο?/strong>

說(shuō)到面向?qū)ο缶褪侨齻€(gè)特性,封裝,多態(tài),繼承。

<1>、子類重寫父類方法

我們?cè)诶^承父類的時(shí)候往往會(huì)重寫父類中的方法,例如

class A:
  def get_name(self):
    return self.name
  def return_name(self):
    if hasattr(self, 'name'):
      return 'name: ' + getattr(self, 'name', None)  
  
  
class B(A):
  name = "b"
  def get_name(self):
    return self.name
  
b = B()
b.get_name() # 輸出B
b.return_name() # 輸出name: B,這里由于B類中沒(méi)有實(shí)現(xiàn)return_name方法,實(shí)例化B得到b之后,會(huì)調(diào)用父類A中的return_name方法,hasattr方法會(huì)查找類中是否有name屬性,這里雖然在類A中沒(méi)有,會(huì)向下查找B類中是否有name屬性,然后返回'name: ' + getattr(self, 'name', None) ,也就是name:b

這是簡(jiǎn)單的子類方法重寫父類中的方法,我們?cè)偈褂胐rf的認(rèn)證,權(quán)限等組件是會(huì)經(jīng)常對(duì)父類中的方法重寫,從而細(xì)粒度的實(shí)現(xiàn)自己的功能。

請(qǐng)注意:事情往往不是絕對(duì)的,如果像重寫python內(nèi)置的基本數(shù)據(jù)類型,如字典,列表中的特殊方法,就會(huì)的到意想不到的結(jié)果,就是實(shí)例化的對(duì)象不再調(diào)用你重寫的方法,而是調(diào)用本來(lái)的方法。這是因?yàn)?code>python的一些基本類型的方法是由c語(yǔ)言編寫的,python為了滿足速度,抄近道不會(huì)再調(diào)用你重寫的特殊方法。

<2>、mixin模式

class X(object):
  def f(self):
    print( 'x')

class A(X):
  def f(self):
    print('a')

  def extral(self):
    print('extral a')

class B(X):
  def f(self):
    print('b')

  def extral(self):
    print( 'extral b')

class C(A, B, X):
  def f(self):
    super(C, self).f()
    print('c')

print(C.mro())

c = C()
c.f()
c.extral()

這樣做也可以輸出結(jié)果

[<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.X'>, <class 'object'>] # 繼承的順序是 A-->B-->X-->object 這了的object在python3中是一切類的基類,包括object類本身。
a
c
extral a # 雖然類C中沒(méi)有實(shí)現(xiàn)接口extral(),卻調(diào)用了父類A中的extral()方法

這樣的繼承雖然可以實(shí)現(xiàn)功能,但是有一個(gè)很明顯的問(wèn)題,那就是在面向?qū)ο笾?,一定要指明一個(gè)類到底是什么。也就是說(shuō),如果我想構(gòu)造一個(gè)類,假如是Somthing,那么我想讓這個(gè)類實(shí)現(xiàn)會(huì)飛,會(huì)游泳,會(huì)跑,三種行為,我可以這樣做,同時(shí)繼承,鳥(niǎo),魚(yú),馬三個(gè)類,像這樣

class Bird:
  def fly(self):
    print('fly')

class Fish:
  def swim(self):
    print('swim')
    
class Horse:
  def run(self):
    print('run')
    
    
class Something(Bird, Fish, Horse):
  pass


s = Something()
s.fly()
s.swim()
s.run()

輸出

fly
swim
run

可是實(shí)現(xiàn)會(huì)跑,會(huì)飛,會(huì)游泳的三種行為,但是這個(gè)類到底是什么,是魚(yú),是馬,還是鳥(niǎo),也就是說(shuō)不知道Something到底是個(gè)什么類。為了解決這個(gè)問(wèn)題,我們可以引用mixin模式。改寫如下

class BirdMixin:
  def fly(self):
    print('fly')

class FishMixin:
  def swim(self):
    print('swim')
    
class Horse:
  def run(self):
    print('run')
    
    
class Something(BirdMixin, FishMixin, Horse):
  pass

這樣就解決了上面的問(wèn)題,也許你會(huì)發(fā)現(xiàn),這其實(shí)沒(méi)有什么變化,只是在類的命名加上了以Mixin結(jié)尾,其實(shí)這是一種默認(rèn)的聲明,告訴你,Something類其實(shí)是一種馬,父類是HorseHorse,繼承其他兩個(gè)類,只是為了調(diào)用他們的方法而已,這種叫做mixin模式,在drf的源碼種會(huì)用到。

例如drf中的generics 路徑為rest_framework/generics.py

class CreateAPIView(mixins.CreateModelMixin,
          GenericAPIView):
  pass


class ListAPIView(mixins.ListModelMixin,
         GenericAPIView):
  pass


class RetrieveAPIView(mixins.RetrieveModelMixin,
           GenericAPIView):
  pass

相當(dāng)于每多一次繼承,子類可調(diào)用的方法就更多了。

二、生成項(xiàng)目

1、生成項(xiàng)目

這里可以使用pycharm作為集成開(kāi)發(fā)工具,創(chuàng)建django項(xiàng)目查看Python和第三方庫(kù)源碼很方便,使用pycharm創(chuàng)建一個(gè)django項(xiàng)目,然后將django rest framework作為第三方包放入django項(xiàng)目中

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

2、數(shù)據(jù)庫(kù)設(shè)計(jì)

先來(lái)看一下如果不使用drf怎么進(jìn)行用戶認(rèn)證,通常是用字段驗(yàn)證的方式,來(lái)生成相應(yīng)的數(shù)據(jù)庫(kù),在用戶登錄時(shí)候,對(duì)數(shù)據(jù)庫(kù)查詢,簡(jiǎn)單的數(shù)據(jù)庫(kù)設(shè)計(jì)如下

from django.db import models


class UserInfo(models.Model):
  USER_TYPE = (
    (1,'普通用戶'),
    (2,'VIP'),
    (3,'SVIP')
  )

  user_type = models.IntegerField(choices=USER_TYPE, default=1)
  username = models.CharField(max_length=32)
  password = models.CharField(max_length=64)

class UserToken(models.Model):
  user = models.OneToOneField(UserInfo,on_delete=models.CASCADE)
  token = models.CharField(max_length=64)

簡(jiǎn)單的用戶信息,每個(gè)用戶關(guān)聯(lián)一個(gè)一對(duì)一的usertoken做為驗(yàn)證

然后在項(xiàng)目目錄下執(zhí)行生成數(shù)據(jù)庫(kù)命令

python manage.py makemigrations
python manage.py migrate

3、路由系統(tǒng)

from django.contrib import admin
from django.urls import path
from django.conf.urls import url

from api.views import AuthView


urlpatterns = [
  path('admin/', admin.site.urls),
  url(r'^api/v1/auth/$', AuthView.as_view())
]

api/v1/auth/中的api分別代表接口和版本號(hào),后面會(huì)說(shuō)到

4、視圖函數(shù)

md5函數(shù)根據(jù)用戶名和用戶的訪問(wèn)時(shí)間進(jìn)行加密

當(dāng)用戶第一次訪問(wèn)時(shí),數(shù)據(jù)庫(kù)創(chuàng)建用戶,并將token字符串,存儲(chǔ)到數(shù)據(jù)庫(kù)

當(dāng)用戶下次訪問(wèn)的時(shí)候,需要帶著這個(gè)字符串與數(shù)據(jù)庫(kù)比對(duì),并返回相應(yīng)的提示信息

這里的token暫時(shí)沒(méi)有放回瀏覽器端,真正項(xiàng)目中可以寫入到瀏覽器cookie中

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

from api import models


def md5(user):
  import hashlib
  import time

  # 當(dāng)前時(shí)間,相當(dāng)于生成一個(gè)隨機(jī)的字符串
  ctime = str(time.time())

  # token加密
  m = hashlib.md5(bytes(user, encoding='utf-8'))
  m.update(bytes(ctime, encoding='utf-8'))
  return m.hexdigest()


class AuthView(View):

  def get(self, request, *args, **kwargs):
    ret = {'code': 1000, 'msg': 'success', 'name': '偷偷'}
    ret = json.dumps(ret, ensure_ascii=False)

    return HttpResponse(ret)

  def post(self, request, *args, **kwargs):
    ret = {'code': 1000, 'msg': None}
    try:
      user = request.POST.get('username')
      pwd = request.POST.get('password')
      obj = models.UserInfo.objects.filter(username=user).first()

      if not obj:
        # 如果用戶第一次登陸則創(chuàng)建用戶
        obj = models.UserInfo.objects.create(username=user, password=pwd)
        ret['code'] = 1001
        ret['msg'] = '創(chuàng)建用戶成功'

      # 為用戶創(chuàng)建token
      token = md5(user)
      # 存在就更新,不存在就創(chuàng)建
      models.UserToken.objects.update_or_create(user=obj, defaults={'token': token})
      ret['token'] = token
    except Exception as e:
      ret['code'] = 1002
      ret['msg'] = '請(qǐng)求異常'
    return JsonResponse(ret)

第一次發(fā)送請(qǐng)求

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

返回請(qǐng)求信息

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

第二次發(fā)送請(qǐng)求

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

返回請(qǐng)求信息

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

這里沒(méi)有使用drf的認(rèn)證組件

三、使用Django rest framewok 認(rèn)證組件

1、實(shí)例

假如用戶想獲取自己的訂單信息,發(fā)送請(qǐng)求之后返回訂單信息以json格式的數(shù)據(jù)返回。

from rest_framework.views import APIView
from django.http import JsonResponse
from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions

from api import models


# 這里直接表示訂單
ORDER_DICT = {
  1:{
    'name':'apple',
    'price':15
  },
  2:{
    'name':'狗子',
    'price':100
  }
}


class FirstAuthenticate(BaseAuthentication):
  # 添加自己的認(rèn)證邏輯,基類BaseAuthentication中有一個(gè)必須要重寫的接口

  def authenticate(self, request):
    pass

  def authenticate_header(self, request):
    pass


class MyAuthenticate(BaseAuthentication):
  # 添加自己的認(rèn)證邏輯,基類BaseAuthentication中有兩個(gè)必須要重寫的接口

  def authenticate(self, request):
    token = request._request.GET.get('token') # 獲取token參數(shù)
    token_obj = models.UserToken.objects.filter(token=token).first() # 在數(shù)據(jù)庫(kù)UserToken查找是否有相應(yīng)的對(duì)象
    if not token_obj: # 如果沒(méi)有,則報(bào)錯(cuò)
      raise exceptions.AuthenticationFailed('用戶認(rèn)證失敗')
    return (token_obj.user, token_obj) # 這里需要返回兩個(gè)對(duì)象,分別是UserInfo對(duì)象和UserToken對(duì)象
 
  def authenticate_header(self, request): # 返回相應(yīng)頭信息
     pass


class OrderView(APIView):
  # 用戶想要獲取訂單,就要先通過(guò)身份認(rèn)證、
  # 這里的authentication_classes 就是用戶的認(rèn)證類
  authentication_classes = [FirestAuthenticate, MyAuthenticate]
  
  def get(self, request, *args, **kwargs):
    ret = {
      'code': 1024,
      'msg': '訂單獲取成功',
    }
    try:
      ret['data'] = ORDER_DICT
    except Exception as e:
      pass
    return JsonResponse(ret)

這里繼承了rest framek中的APIView,在APIView中將原生的request進(jìn)行了封裝,封裝了一些用于認(rèn)證,權(quán)限的類,在請(qǐng)求來(lái)的時(shí)候,會(huì)依次通過(guò)FirestAuthenticate, MyAuthenticate兩個(gè)類,并調(diào)用authenticate進(jìn)行認(rèn)證。

發(fā)送請(qǐng)求

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

返回訂單的數(shù)據(jù)

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

認(rèn)證成功

2、源碼分析

這里推薦使用pycharm作為集成開(kāi)發(fā)工具,可以ctrl+鼠標(biāo)左鍵點(diǎn)擊方法,或者類直接進(jìn)入源碼查看

<1>、第1步

在路由匹配之后會(huì)先進(jìn)入到APIView中的as_view方法中,然后進(jìn)入到djangoView中,

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

<2>、第2步

由于子類APIView已經(jīng)實(shí)現(xiàn)了dispath方法,接著返回APIView中的disapth方法

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

<3>、第3步

然后會(huì)發(fā)現(xiàn)drf對(duì)原生request做的操作

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

<4>、第4步

這里的initialize_request,主要進(jìn)行封裝

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

<5>、第5步

而initial則會(huì)對(duì)調(diào)用封裝類中的方法,實(shí)現(xiàn)各種功能

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

至此可以看到requestdrf中大概的流程。

3、drf認(rèn)證流程

在上面第4步和第5步可以看到APIView中的兩個(gè)方法的initialize_request,initial

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

我們進(jìn)入到initialize_request,查看authenticators=self.get_authenticators()

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

這里的authentication_classes,其實(shí)是一個(gè)所有認(rèn)證類的集合(指的是一個(gè)可以迭代的容器對(duì)象,如list,tuple等,而不是特指set()內(nèi)置類型),

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

這里的api_settings其實(shí)就是django項(xiàng)目的全局配置文件settings.py,這說(shuō)明我們可以在需要認(rèn)證的視圖函數(shù)多的情況下使用全局配置使得每一個(gè)進(jìn)行認(rèn)證。

<1>、全局與局部配置認(rèn)證類

可以直接在settings.py中添加全局配置項(xiàng)

REST_FRAMEWORK = {
  'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.authenticate.FirstAuthenticate', 'api.utils.authenticate.MyAuthenticate'],
}

那么如果我的個(gè)別視圖類不想認(rèn)證呢?可以這樣寫

class OrderView(APIView):
  # 這里沒(méi)有重寫authentication_classes屬性,則使用全局配置的authentication_classes,即在setting.py中的authentication_classes。
  def get(self, request, *args, **kwargs):
     pass

class CartView(APIView):
   authentication_classes = [authenticate.FirstAuthenticate,] # authentication_classes中只包含F(xiàn)irstAuthenticate,則只通過(guò)他的認(rèn)證
  def get(self, request, *args, **kwargs):
     pass

class UserInfoView(APIView):
  authentication_classes = [] # authentication_classes為空,則不會(huì)進(jìn)行認(rèn)證
  def get(self, request, *args, **kwargs):
     pass

<2>、究竟如何進(jìn)行認(rèn)證

上面說(shuō)了想要定義多個(gè)認(rèn)證規(guī)則,其實(shí)就是封裝多個(gè)認(rèn)證類,那么這些認(rèn)證類如何進(jìn)行認(rèn)證呢?

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

這里的perform_authentication就是進(jìn)行主要的功能,在request類中有一個(gè)_authenticate

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

來(lái)分析下源碼

def _authenticate(self):
    """
    Attempt to authenticate the request using each authentication instance
    in turn.
    """
    for authenticator in self.authenticators: # 找到 authentication_classes,并循環(huán)每一個(gè)認(rèn)證類
      try:
        user_auth_tuple = authenticator.authenticate(self) # 調(diào)用認(rèn)證類的authenticate方法,也就是上面我們實(shí)現(xiàn)的方法,并將返回值賦值給user_auth_tuple
      except exceptions.APIException:
        self._not_authenticated() # 如果出錯(cuò)調(diào)用_not_authenticated,方法,下面會(huì)說(shuō)到
        raise

      if user_auth_tuple is not None: # 如果authenticate方法的返回值不為空
        self._authenticator = authenticator
        self.user, self.auth = user_auth_tuple # 這也就是為什么認(rèn)證類的authenticate方法會(huì)返回兩個(gè)對(duì)象的原因
        return

    self._not_authenticated() # 如果沒(méi)有通過(guò)認(rèn)證,則調(diào)用_not_authenticated方法

  def _not_authenticated(self):
    """
    Set authenticator, user & authtoken representing an unauthenticated request.

    Defaults are None, AnonymousUser & None.
    """
    self._authenticator = None

    if api_settings.UNAUTHENTICATED_USER:
      self.user = api_settings.UNAUTHENTICATED_USER()
    else:
      self.user = None

    if api_settings.UNAUTHENTICATED_TOKEN:
      self.auth = api_settings.UNAUTHENTICATED_TOKEN()
    else:
      self.auth = None

_authenticate方法中調(diào)用authenticator.authenticate(self) 方法,返回給user_auth_tuple,并通過(guò)判斷user_auth_tuple是否為空,其實(shí)就像是我從瀏覽器發(fā)送請(qǐng)求,request中攜帶我的用戶認(rèn)證信息,在進(jìn)入視圖類之前,通過(guò)一次一次調(diào)用認(rèn)證類來(lái)查看我攜帶的認(rèn)證信息是否正確,如果正確則返回?cái)?shù)據(jù)庫(kù)中正確的User對(duì)象。如果不通過(guò)或者沒(méi)有認(rèn)證信息,則在_not_authenticated中按照匿名用戶處理。

來(lái)看一下authenticator.authenticate(self)中的authenticate(self)具體做了什么

Django Rest framework之認(rèn)證的實(shí)現(xiàn)代碼

在authenticate中可以添加具體的認(rèn)證邏輯,當(dāng)然也可以在視圖類中書(shū)寫,但是drf中提供的組件,可以使得代碼耦合度更低,維護(hù)性更強(qiáng),更方便。

<3>、匿名用戶認(rèn)證

上面_not_authenticatedUNAUTHENTICATED_TOKEN,UNAUTHENTICATED_USER說(shuō)明,也可以通過(guò)在setting.py中定義匿名用戶的認(rèn)證。
只要再setting.py中添加如下

REST_FRAMEWORK = {
  'DEFAULT_AUTHENTICATION_CLASSES': ['api.utils.authenticate.FirstAuthenticate', 'api.utils.authenticate.MyAuthenticate'],
  "UNAUTHENTICATED_USER": None, # 匿名,request.user = None
  "UNAUTHENTICATED_TOKEN": None,# 匿名,request.auth = None
}

4、認(rèn)證總結(jié)

要理解django rest framework ,就要先理解面向?qū)ο蟆W宇惱^承父類屬性和方法,而在基類中往往以定義抽象接口的形式,強(qiáng)制使子類重寫抽象接口。不過(guò)抽象接口這往往是框架開(kāi)發(fā)者做的,而不是我們要需要做的。實(shí)例化的對(duì)象可以調(diào)用所類的屬性和方法,其實(shí)方法也可以看作是一種屬性。子類新定義或者重寫父類的屬性,實(shí)例化的對(duì)象可以調(diào)用父類中的方法查詢到子類的屬性,就是說(shuō)實(shí)例化的對(duì)象集所有父類子類于一身。子類中的方法或者屬性會(huì)覆蓋掉父類中的方法和屬性,實(shí)例化對(duì)象調(diào)用的時(shí)候不會(huì)管父類中怎么樣,所以在變量和方法命名的時(shí)候應(yīng)該注意,或者也可以使用super等操作。

而在django rest framework中,對(duì)原生request做了封裝。原本我們可以再視圖類中的進(jìn)行的比如訪問(wèn)限流,用戶認(rèn)證,權(quán)限管理等邏輯,封裝到一個(gè)一個(gè)類中的方法中,在用戶請(qǐng)求進(jìn)入視圖類之前,會(huì)先查找并迭代相關(guān)封裝的類,然后調(diào)用這些類的相關(guān)方法,根據(jù)返回值判斷是否滿足認(rèn)證,權(quán)限等功能。如果不通過(guò)則不會(huì)進(jìn)入到視圖類執(zhí)行下一步,并返回相應(yīng)的提示信息。這樣分開(kāi)的好處是當(dāng)然就是最大程度的解耦,各個(gè)相關(guān)功能相互不影響,又相互關(guān)聯(lián),維護(hù)性更高。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持億速云。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI