1. 程式人生 > >基於django 開發的框架 jumpserver 原始碼解析(一)

基於django 開發的框架 jumpserver 原始碼解析(一)

基於類的檢視,以及url 路由解析。

  jumpserver 這個輪子是好跑的輪子,又大又圓,對原始碼進行解析。

 

jumpserver  中 用了 大量的基於類的檢視函式,相對抽象一點,隱藏了一些細節。大量使用 類似下面的url路由。

urlpatterns = [
    url(r'^v1/assets-bulk/$', api.AssetListUpdateApi.as_view(), name='asset-bulk-update')]

跟 基於函式的檢視不一樣, 配置類檢視的時候,需要使用類檢視的as_view()方法來註冊新增,

as_view 方法 是django 內建base 類中,view類的 類方法。下面貼出原始碼

class View:
    """
    Intentionally simple parent class for all views. Only implements
    dispatch-by-method and simple sanity checking.
    """

    http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

    def __init__(self, **kwargs):
        """
        Constructor. Called in the URLconf; can contain helpful extra
        keyword arguments, and other things.
        """
        # Go through keyword arguments, and either save their values to our
        # instance, or raise an error.
        for key, value in kwargs.items():
            setattr(self, key, value)

    @classonlymethod
    def as_view(cls, **initkwargs):
        """Main entry point for a request-response process."""
        for key in initkwargs:
            if key in cls.http_method_names:
                raise TypeError("You tried to pass in the %s method name as a "
                                "keyword argument to %s(). Don't do that."
                                % (key, cls.__name__))
            if not hasattr(cls, key):
                raise TypeError("%s() received an invalid keyword %r. as_view "
                                "only accepts arguments that are already "
                                "attributes of the class." % (cls.__name__, key))

        def view(request, *args, **kwargs):
            self = cls(**initkwargs)
            if hasattr(self, 'get') and not hasattr(self, 'head'):
                self.head = self.get
            self.request = request
            self.args = args
            self.kwargs = kwargs
            return self.dispatch(request, *args, **kwargs)
        view.view_class = cls
        view.view_initkwargs = initkwargs

        # take name and docstring from class
        update_wrapper(view, cls, updated=())

        # and possible attributes set by decorators
        # like csrf_exempt from dispatch
        update_wrapper(view, cls.dispatch, assigned=())
        return view

as_view 方法返回得是一個函式的引用view, view 方法是 as_view 方法的類方法中的一個內建方法,這個方法 作用是 例項化了一個View類,然後 返回的是例項的dispatch方法。那麼dispath 方法 作用是什麼呢?下面貼出dispath 方法原始碼。

 def dispatch(self, request, *args, **kwargs):
        # Try to dispatch to the right method; if a method doesn't exist,
        # defer to the error handler. Also defer to the error handler if the
        # request method isn't on the approved list.
        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
        return handler(request, *args, **kwargs)

dispath  先對request  的 method 做了一個判斷,返回了handler ,這個handler 是個什麼東東?handler 是通過 pythong 內建方法發得到的,下面貼出getattr 方法原始碼。

def getattr(object, name, default=None): # known special case of getattr
    """
    getattr(object, name[, default]) -> value
    
    Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
    When a default argument is given, it is returned when the attribute doesn't
    exist; without it, an exception is raised in that case.
    """

getattr 方法發是得到 一個物件 屬性或者 方法的引用,django使用這個方法實現了一個反射機制,根據request物件的method 屬性,對應 對應試圖類的相應方法,如果request 的method 屬性 不在 http_method_names  這個列表裡面 ,在返回error 檢視類。