django restframework

1、django restframework 請求流程源碼剖析python

 

上面的認證一個流程是rest_framework的關於APIauth的認證流程,,這個流程試用權限、頻率、版本、認證、這個四個組件都是經過類似的流程進行實現,不一樣的組件,是在initial()這個方法中調用不一樣的方法來進行執行的,同時在剖析源碼的過程當中,咱們整個rest_framework總共分爲10個組件,每一中組件均可以進行全局配置,和局部配置,下面依次介紹這10個組件。django

一、認證auth()json

上面流程已經提到,API認證,每個認證類的,真正的驗證是執行了一個authenticate()方法,在自定義認證類時,須要重寫這個authenticate()方法便可。同時,rest——framework提供了幾個認證類from rest_framework.authentication 能夠經過查看提供的認證類,在自定製時,能夠繼承這個裏面的基類。後端

而authenticate()方法的返回值,一共有三種,第一種,認證不經過報錯。第二種認證經過返回一個元組,元組中的內容是user對象和token對象。第三種是None,默認就是匿名用戶api

from rest_framework import exceptions

from rest_framework.authentication import BaseAuthentication
from django.http import JsonResponse
from app01 import models
import time ,hashlib

class MyAuthtication(BaseAuthentication):
    '''用戶api驗證'''

    def authenticate(self ,request):
        token = request.GET.get('token')
        token_obj = models.Token.objects.filter(token=token).first()
        if  not token_obj:
            raise exceptions.AuthenticationFailed('用戶認證失敗')
        return ( token_obj.user,  token_obj)

    def authenticate_header(self ,request):
        pass
from rest_framework import exceptions 關於說到的若是認證失敗,須要報錯,reset_framework是要返回指定報錯的
raise exceptions.AuthenticationFailed ,這個主動觸發這個AuthenticationFailed,報錯,默認超類中會抓取這個異常,response返回。

全局配置和局部配置緩存

全局app

REST_FRAMEWORK =
{'DEFAULT_AUTHENTICATION_CLASSES':['app01.utils.auth.MyAuthtication',],
                 'UNAUTHENTICATED_USER':lambda:None}


一、在settings文件中 ,按照上述配置,認證類是能夠有多個的,因此DEFAULT_AUTHENTICATION_CLASSES,這個key對應的是一個列表。
app01.utils.auth是認證類的路徑。


二、關於咱們說認證返回有三種結果,若是是未登陸用戶是,返回的信息是None,這個也能夠進行定製,返回指定的信息,按照第二行配置

  

局部配置 前後端分離

class AuthView(APIView):
    authentication_classes = [BasicAuthentication,]


在視圖中按照上面配置便可

  

 

二、權限(permission)post

2.1權限的是經過 此方法進行判斷的 ,在重寫的時候,重寫這個has_premission方法便可,固然rest_framework,提供了幾個默認的權限類供使用,from rest_framework.permissions  ,經過這個permissions  文件查找幾種提供的權限類,重寫時能夠繼承。url

    def check_permissions(self, request):
        """
        Check if the request should be permitted.
        Raises an appropriate exception if the request is not permitted.
        """
        for permission in self.get_permissions():
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request, message=getattr(permission, 'message', None)
                )

has_premission()方法 。而這方法的返回值,一種是True,帶表有權限,False表明沒有權限。

  

2.2全局配置和局部配置

全局配置 

REST_FRAMEWORK ={
                 'DEFAULT_PERMISSION_CLASSES':['app01.utils.auth.MyPremission']}

  

局部配置

from rest_framework.permissions import BasePermission

class AuthView(APIView):
    permission_classes = [BasePermission,]

  

三、頻率(throttle)

3.1這個組件又稱之爲節流,這個做用就是現實一個api,在一個固定時間段內可以訪問幾回 , 是調用了每個節流類的allow_request方法進行判斷的。這個能夠重寫也能夠直接調用rest_framework提供的,從

from rest_framework.throttling 獲取,裏面的總體實現原理是相似的。同時這個地方要注意,咱們是以ip地址仍是用戶來識別是不是同一個用戶的,若是是匿名用戶就能夠用ip地址,若是是登陸用戶能夠用用戶名或者用戶id均可以。可是本質上,是沒法真正實現這個限制訪問的。

    def check_throttles(self, request):
        """
        Check if request should be throttled.
        Raises an appropriate exception if the request is throttled.
        """
        for throttle in self.get_throttles():
            if not throttle.allow_request(request, self):
                self.throttled(request, throttle.wait())  

allow_request()方法返回兩個結果,一個是True,表明有權限,一個是False,沒有權限。

 

3.2所有和局部配置

全局

REST_FRAMEWORK ={DEFAULT_THROTTLE_RATES':{'all':'3/m'},
DEFAULT_THROTTLE_CLASSES:['app01.utils.auth.MyPremission']
} 


關於這個節流的配置 ,後面的scope是說的是實際設置的默認頻率,是每分鐘3次的意思,能夠看源碼,這個單位不止分鐘。 關於這個scope是須要在自定義的節流類中配置的。 通常使用這個SimpleRateThrottle就夠用了
class VisitorThrottle(SimpleRateThrottle):
scope = 'all'
def get_cache_key(self, request, view):
'''這個就是返回一個放在django緩存中的key,
能夠根據用戶id,或者ip地址來而後返回這個ip這個字符串,
或者用用戶id'''
return ip或者用戶id

  

局部

class AuthView(APIView):
    throttle_classes = []

將本身寫的自定製的類導入,放到這個列表中便可

  

 

四、版本(version)

4.1版本認證是經過這個方法實現的

def determine_version(self, request, *args, **kwargs):
        """
        If versioning is being used, then determine any API version for the
        incoming request. Returns a two-tuple of (version, versioning_scheme)
        """
        if self.versioning_class is None:  
            return (None, None)
        scheme = self.versioning_class()  #去配置中版本類,實例化
        return (scheme.determine_version(request, *args, **kwargs), scheme)
                 #返回這個實例的determine_version()方法的調用結果 ,和這個實例

這個determine_version() 方法只有兩種返回結果,一個是返回版本信息,一個報異常。

  

4.2 全局配置與局部配置

全局配置

關於版本的認證,徹底不可用rest_framework提供的版本認證的類進行一個全局配置 ,能夠經過from rest_framework.versioning,獲取

    def determine_version(self, request, *args, **kwargs):
        version = kwargs.get(self.version_param, self.default_version)
        if version is None:
            version = self.default_version


一、這個是獲取版本的源碼,能夠看到他是從URL中獲取一個參數,這個參數,設置的是version_param ,因此,這個地方設置的是什麼參數,URL上就要默認的別名要與這個參數一致,,例如:

url('api/(?P<version>v1+)/order$' ,views.OrderView.as_view() ,name='uuu')


REST_FRAMEWORK ={      'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning' ,
                  'VERSION_PARAM':'version',
                  'ALLOWED_VERSIONS':['v1' ,'v2']
                }


二、咱們看到還有一個ALLOWED_VERSIONS這個參數,這個參數是默認當前有多少個個版本號,加入說咱們只有兩個版本,可是URL中去是一個v100,不在這個範圍內,也會報錯。

  

 

 

五、解析器

5.一、 做用,用來解析發送的post請求中的請求體的數據,當post請求頭中ContentType不在是x-www-form-urlencode 和請求體的數據格式是 name=eric&age=26 時, 經過request.POST是拿不到請求體中的數據的。

同時,咱們的ContentType,能夠決定,發送post請求時,post請求體中的數格格式。而在MVC這種先後端分離的結構中,數據都是經過json進行傳輸的。

因此,請求頭中的ContentType 就會變成application/json 格式,這個時候請求體中的數據格式也發生變化,能夠是{"name":"eric","age":18},這裏面有一個細節 就是必定是雙引號,否則restframework,內部的loads反序列化不了會報錯。

 

二、解析器源碼剖析流程

 

六、序列化(serialize)

序列化主要有兩方面功能,第一是序列化,第二個就是數據驗證,其實序列化,和django自己的form和ModelForm很是類似

6.1 序列化源碼流程

 

6.2驗證源碼流程

 

七、分頁(pagination)

 

八、視圖(view)

 

九、路由

 

十、渲染器

相關文章
相關標籤/搜索