Django中CBV和Restful API中的APIView源码分析

Django中CBV和Restful API中的APIView源码分析

python的Django框架的视图处理可以用FBV, 也可以采用CBV。首先定义一个CBV视图:

from django.views import Viewfrom django.http import JsonResponseclass Book(View):    def get(self, request):        ll = [{‘key‘:value}]        return JsonResponse(ll, safe=false, json_dumps_params={‘ensure‘:false})    def post(self, request):        return HttpResponse(‘ok‘)    

#前台路由的配置 url(r‘^books/‘, views.Books.as_view()),

首先,一个CBV(class base views 类方式完成视图响应)视图定义时类方法的名称必须有请求名,为什么要这样定义?

首先,由路由的分发可以看出,

从继承的父类View开始:

views.Books.as_view() ,其实是调用了我们自定义视图模型类Book的as_view函数,可是明明自己未定义该函数,那么需要去父类观察。

源码:--------------分析以注释说明-----------------------

class View(object):    """    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 six.iteritems(kwargs):            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?    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)?    def http_method_not_allowed(self, request, *args, **kwargs):        logger.warning(            ‘Method Not Allowed (%s): %s‘, request.method, request.path,            extra={‘status_code‘: 405, ‘request‘: request}        )        return http.HttpResponseNotAllowed(self._allowed_methods())?    def options(self, request, *args, **kwargs):        """        Handles responding to requests for the OPTIONS HTTP verb.        """        response = http.HttpResponse()        response[‘Allow‘] = ‘, ‘.join(self._allowed_methods())        response[‘Content-Length‘] = ‘0‘        return response?    def _allowed_methods(self):        return [m.upper() for m in self.http_method_names if hasattr(self, m)]?

Restful API中的APIView

在Django中的RestfulAPI 的CBV定义

from rest_framework.views import APIViewclass Books(APIView):    def get(self, request):        # 获取所有的图书:        books = Book.objects.all()        # print(books)        ll = []        for book in books:            # print(book.id)            # print(book.name)            # print(book.author)            dic = {                "id": book.id,                "name": book.name,                "author": book.author            }            ll.append(dic)            return render(request, ‘show_books.html‘, locals())        # return JsonResponse(ll, safe=False, json_dumps_params={‘ensure_ascii‘: False}            # 增加图书    def post(self, request):        id = request.data[‘id‘]        name = request.data[‘name‘]        author = request.data[‘author‘]        print(id, name, author)        Book.objects.create(id=id, name=name, author=author)        return redirect(‘/books/‘)? # 路由分发 url(r‘^books/‘, views.Books.as_view()),

定义方式和Django继承的父类不同,但是路由分发相同

那么我们需要看继承的父类APIView如何处理

源码:

?

Request源码

class Request(object):    """    Wrapper allowing to enhance a standard `HttpRequest` instance.?    Kwargs:        - request(HttpRequest). The original request instance.        - parsers_classes(list/tuple). The parsers to use for parsing the          request content.        - authentication_classes(list/tuple). The authentications used to try          authenticating the request‘s user.    """?    def __init__(self, request, parsers=None, authenticators=None,                 negotiator=None, parser_context=None):        assert isinstance(request, HttpRequest), (            ‘The `request` argument must be an instance of ‘            ‘`django.http.HttpRequest`, not `{}.{}`.‘            .format(request.__class__.__module__, request.__class__.__name__)        )?        self._request = request        self.parsers = parsers or ()        self.authenticators = authenticators or ()        self.negotiator = negotiator or self._default_negotiator()        self.parser_context = parser_context        self._data = Empty        self._files = Empty        self._full_data = Empty        self._content_type = Empty        self._stream = Empty?        if self.parser_context is None:            self.parser_context = {}        self.parser_context[‘request‘] = self        self.parser_context[‘encoding‘] = request.encoding or settings.DEFAULT_CHARSET?        force_user = getattr(request, ‘_force_auth_user‘, None)        force_token = getattr(request, ‘_force_auth_token‘, None)        if force_user is not None or force_token is not None:            forced_auth = ForcedAuthentication(force_user, force_token)            self.authenticators = (forced_auth,)?    def _default_negotiator(self):        return api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS()?    @property    def content_type(self):        meta = self._request.META        return meta.get(‘CONTENT_TYPE‘, meta.get(‘HTTP_CONTENT_TYPE‘, ‘‘))?    @property    def stream(self):        """        Returns an object that may be used to stream the request content.        """        if not _hasattr(self, ‘_stream‘):            self._load_stream()        return self._stream?    @property    def query_params(self):        """        More semantically correct name for request.GET.        """        return self._request.GET?    @property    def data(self):        if not _hasattr(self, ‘_full_data‘):            self._load_data_and_files()        return self._full_data?    @property    def user(self):        """        Returns the user associated with the current request, as authenticated        by the authentication classes provided to the request.        """        if not hasattr(self, ‘_user‘):            with wrap_attributeerrors():                self._authenticate()        return self._user?    @user.setter    def user(self, value):        """        Sets the user on the current request. This is necessary to maintain        compatibility with django.contrib.auth where the user property is        set in the login and logout functions.?        Note that we also set the user on Django‘s underlying `HttpRequest`        instance, ensuring that it is available to any middleware in the stack.        """        self._user = value        self._request.user = value?    @property    def auth(self):        """        Returns any non-user authentication information associated with the        request, such as an authentication token.        """        if not hasattr(self, ‘_auth‘):            with wrap_attributeerrors():                self._authenticate()        return self._auth?    @auth.setter    def auth(self, value):        """        Sets any non-user authentication information associated with the        request, such as an authentication token.        """        self._auth = value        self._request.auth = value?    @property    def successful_authenticator(self):        """        Return the instance of the authentication instance class that was used        to authenticate the request, or `None`.        """        if not hasattr(self, ‘_authenticator‘):            with wrap_attributeerrors():                self._authenticate()        return self._authenticator?    def _load_data_and_files(self):        """        Parses the request content into `self.data`.        """        if not _hasattr(self, ‘_data‘):            self._data, self._files = self._parse()            if self._files:                self._full_data = self._data.copy()                self._full_data.update(self._files)            else:                self._full_data = self._data?            # if a form media type, copy data & files refs to the underlying            # http request so that closable objects are handled appropriately.            if is_form_media_type(self.content_type):                self._request._post = self.POST                self._request._files = self.FILES?    def _load_stream(self):        """        Return the content body of the request, as a stream.        """        meta = self._request.META        try:            content_length = int(                meta.get(‘CONTENT_LENGTH‘, meta.get(‘HTTP_CONTENT_LENGTH‘, 0))            )        except (ValueError, TypeError):            content_length = 0?        if content_length == 0:            self._stream = None        elif not self._request._read_started:            self._stream = self._request        else:            self._stream = io.BytesIO(self.body)?    def _supports_form_parsing(self):        """        Return True if this requests supports parsing form data.        """        form_media = (            ‘application/x-www-form-urlencoded‘,            ‘multipart/form-data‘        )        return any([parser.media_type in form_media for parser in self.parsers])?    def _parse(self):        """        Parse the request content, returning a two-tuple of (data, files)?        May raise an `UnsupportedMediaType`, or `ParseError` exception.        """        media_type = self.content_type        try:            stream = self.stream        except RawPostDataException:            if not hasattr(self._request, ‘_post‘):                raise            # If request.POST has been accessed in middleware, and a method=‘POST‘            # request was made with ‘multipart/form-data‘, then the request stream            # will already have been exhausted.            if self._supports_form_parsing():                return (self._request.POST, self._request.FILES)            stream = None?        if stream is None or media_type is None:            if media_type and is_form_media_type(media_type):                empty_data = QueryDict(‘‘, encoding=self._request._encoding)            else:                empty_data = {}            empty_files = MultiValueDict()            return (empty_data, empty_files)?        parser = self.negotiator.select_parser(self, self.parsers)?        if not parser:            raise exceptions.UnsupportedMediaType(media_type)?        try:            parsed = parser.parse(stream, media_type, self.parser_context)        except Exception:            # If we get an exception during parsing, fill in empty data and            # re-raise.  Ensures we don‘t simply repeat the error when            # attempting to render the browsable renderer response, or when            # logging the request or similar.            self._data = QueryDict(‘‘, encoding=self._request._encoding)            self._files = MultiValueDict()            self._full_data = self._data            raise?        # Parser classes may return the raw data, or a        # DataAndFiles object.  Unpack the result as required.        try:            return (parsed.data, parsed.files)        except AttributeError:            empty_files = MultiValueDict()            return (parsed, empty_files)?    def _authenticate(self):        """        Attempt to authenticate the request using each authentication instance        in turn.        """        for authenticator in self.authenticators:            try:                user_auth_tuple = authenticator.authenticate(self)            except exceptions.APIException:                self._not_authenticated()                raise?            if user_auth_tuple is not None:                self._authenticator = authenticator                self.user, self.auth = user_auth_tuple                return?        self._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?    def __getattr__(self, attr):        """        If an attribute does not exist on this instance, then we also attempt        to proxy it to the underlying HttpRequest object.        """        try:            return getattr(self._request, attr)        except AttributeError:            return self.__getattribute__(attr)?    @property    def DATA(self):        raise NotImplementedError(            ‘`request.DATA` has been deprecated in favor of `request.data` ‘            ‘since version 3.0, and has been fully removed as of version 3.2.‘        )?    @property    def POST(self):        # Ensure that request.POST uses our request parsing.        if not _hasattr(self, ‘_data‘):            self._load_data_and_files()        if is_form_media_type(self.content_type):            return self._data        return QueryDict(‘‘, encoding=self._request._encoding)?    @property    def FILES(self):        # Leave this one alone for backwards compat with Django‘s request.FILES        # Different from the other two cases, which are not valid property        # names on the WSGIRequest class.        if not _hasattr(self, ‘_files‘):            self._load_data_and_files()        return self._files?    @property    def QUERY_PARAMS(self):        raise NotImplementedError(            ‘`request.QUERY_PARAMS` has been deprecated in favor of `request.query_params` ‘            ‘since version 3.0, and has been fully removed as of version 3.2.‘        )?    def force_plaintext_errors(self, value):        # Hack to allow our exception handler to force choice of        # plaintext or html error responses.        self._request.is_ajax = lambda: value?
class Request(object):    """    Wrapper allowing to enhance a standard `HttpRequest` instance.

    Kwargs:        - request(HttpRequest). The original request instance.        - parsers_classes(list/tuple). The parsers to use for parsing the          request content.        - authentication_classes(list/tuple). The authentications used to try          authenticating the request‘s user.    """

    def __init__(self, request, parsers=None, authenticators=None,negotiator=None, parser_context=None):        assert isinstance(request, HttpRequest), (            ‘The `request` argument must be an instance of ‘            ‘`django.http.HttpRequest`, not `{}.{}`.‘.format(request.__class__.__module__, request.__class__.__name__)        )

        self._request = request        self.parsers = parsers or ()        self.authenticators = authenticators or ()        self.negotiator = negotiator or self._default_negotiator()        self.parser_context = parser_context        self._data = Empty        self._files = Empty        self._full_data = Empty        self._content_type = Empty        self._stream = Empty

        if self.parser_context is None:            self.parser_context = {}        self.parser_context[‘request‘] = self        self.parser_context[‘encoding‘] = request.encoding or settings.DEFAULT_CHARSET

        force_user = getattr(request, ‘_force_auth_user‘, None)        force_token = getattr(request, ‘_force_auth_token‘, None)        if force_user is not None or force_token is not None:            forced_auth = ForcedAuthentication(force_user, force_token)            self.authenticators = (forced_auth,)

    def _default_negotiator(self):        return api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS()

    @propertydef content_type(self):        meta = self._request.META        return meta.get(‘CONTENT_TYPE‘, meta.get(‘HTTP_CONTENT_TYPE‘, ‘‘))

    @propertydef stream(self):        """        Returns an object that may be used to stream the request content.        """        if not _hasattr(self, ‘_stream‘):            self._load_stream()        return self._stream

    @propertydef query_params(self):        """        More semantically correct name for request.GET.        """        return self._request.GET

    @propertydef data(self):        if not _hasattr(self, ‘_full_data‘):            self._load_data_and_files()        return self._full_data

    @propertydef user(self):        """        Returns the user associated with the current request, as authenticated        by the authentication classes provided to the request.        """        if not hasattr(self, ‘_user‘):            with wrap_attributeerrors():                self._authenticate()        return self._user

    @user.setterdef user(self, value):        """        Sets the user on the current request. This is necessary to maintain        compatibility with django.contrib.auth where the user property is        set in the login and logout functions.

        Note that we also set the user on Django‘s underlying `HttpRequest`        instance, ensuring that it is available to any middleware in the stack.        """        self._user = value        self._request.user = value

    @propertydef auth(self):        """        Returns any non-user authentication information associated with the        request, such as an authentication token.        """        if not hasattr(self, ‘_auth‘):            with wrap_attributeerrors():                self._authenticate()        return self._auth

    @auth.setterdef auth(self, value):        """        Sets any non-user authentication information associated with the        request, such as an authentication token.        """        self._auth = value        self._request.auth = value

    @propertydef successful_authenticator(self):        """        Return the instance of the authentication instance class that was used        to authenticate the request, or `None`.        """        if not hasattr(self, ‘_authenticator‘):            with wrap_attributeerrors():                self._authenticate()        return self._authenticator

    def _load_data_and_files(self):        """        Parses the request content into `self.data`.        """        if not _hasattr(self, ‘_data‘):            self._data, self._files = self._parse()            if self._files:                self._full_data = self._data.copy()                self._full_data.update(self._files)            else:                self._full_data = self._data

            # if a form media type, copy data & files refs to the underlying            # http request so that closable objects are handled appropriately.if is_form_media_type(self.content_type):                self._request._post = self.POST                self._request._files = self.FILES

    def _load_stream(self):        """        Return the content body of the request, as a stream.        """        meta = self._request.META        try:            content_length = int(                meta.get(‘CONTENT_LENGTH‘, meta.get(‘HTTP_CONTENT_LENGTH‘, 0))            )        except (ValueError, TypeError):            content_length = 0

if content_length == 0:            self._stream = None        elif not self._request._read_started:            self._stream = self._request        else:            self._stream = io.BytesIO(self.body)

    def _supports_form_parsing(self):        """        Return True if this requests supports parsing form data.        """        form_media = (            ‘application/x-www-form-urlencoded‘,‘multipart/form-data‘)        return any([parser.media_type in form_media for parser in self.parsers])

    def _parse(self):        """        Parse the request content, returning a two-tuple of (data, files)

        May raise an `UnsupportedMediaType`, or `ParseError` exception.        """        media_type = self.content_type        try:            stream = self.stream        except RawPostDataException:            if not hasattr(self._request, ‘_post‘):                raise# If request.POST has been accessed in middleware, and a method=‘POST‘            # request was made with ‘multipart/form-data‘, then the request stream            # will already have been exhausted.if self._supports_form_parsing():                return (self._request.POST, self._request.FILES)            stream = None

        if stream is None or media_type is None:            if media_type and is_form_media_type(media_type):                empty_data = QueryDict(‘‘, encoding=self._request._encoding)            else:                empty_data = {}            empty_files = MultiValueDict()            return (empty_data, empty_files)

        parser = self.negotiator.select_parser(self, self.parsers)

        if not parser:            raise exceptions.UnsupportedMediaType(media_type)

        try:            parsed = parser.parse(stream, media_type, self.parser_context)        except Exception:            # If we get an exception during parsing, fill in empty data and            # re-raise.  Ensures we don‘t simply repeat the error when            # attempting to render the browsable renderer response, or when            # logging the request or similar.self._data = QueryDict(‘‘, encoding=self._request._encoding)            self._files = MultiValueDict()            self._full_data = self._data            raise

# Parser classes may return the raw data, or a        # DataAndFiles object.  Unpack the result as required.try:            return (parsed.data, parsed.files)        except AttributeError:            empty_files = MultiValueDict()            return (parsed, empty_files)

    def _authenticate(self):        """        Attempt to authenticate the request using each authentication instance        in turn.        """        for authenticator in self.authenticators:            try:                user_auth_tuple = authenticator.authenticate(self)            except exceptions.APIException:                self._not_authenticated()                raise

            if user_auth_tuple is not None:                self._authenticator = authenticator                self.user, self.auth = user_auth_tuple                return

self._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

    def __getattr__(self, attr):        """        If an attribute does not exist on this instance, then we also attempt        to proxy it to the underlying HttpRequest object.        """        try:            return getattr(self._request, attr)        except AttributeError:            return self.__getattribute__(attr)

    @propertydef DATA(self):        raise NotImplementedError(            ‘`request.DATA` has been deprecated in favor of `request.data` ‘            ‘since version 3.0, and has been fully removed as of version 3.2.‘)

    @propertydef POST(self):        # Ensure that request.POST uses our request parsing.if not _hasattr(self, ‘_data‘):            self._load_data_and_files()        if is_form_media_type(self.content_type):            return self._data        return QueryDict(‘‘, encoding=self._request._encoding)

    @propertydef FILES(self):        # Leave this one alone for backwards compat with Django‘s request.FILES        # Different from the other two cases, which are not valid property        # names on the WSGIRequest class.if not _hasattr(self, ‘_files‘):            self._load_data_and_files()        return self._files

    @propertydef QUERY_PARAMS(self):        raise NotImplementedError(            ‘`request.QUERY_PARAMS` has been deprecated in favor of `request.query_params` ‘            ‘since version 3.0, and has been fully removed as of version 3.2.‘)

    def force_plaintext_errors(self, value):        # Hack to allow our exception handler to force choice of        # plaintext or html error responses.self._request.is_ajax = lambda: value

原文地址:https://www.cnblogs.com/5j421/p/10597744.html

时间: 2024-08-02 07:03:27

Django中CBV和Restful API中的APIView源码分析的相关文章

Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析

目录 0.前言 1.TemporalAccessor源码 2.Temporal源码 3.TemporalAdjuster源码 4.ChronoLocalDate源码 5.LocalDate源码 6.总结 0.前言 通过前面Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类中主要的类关系简图如下: 可以看出主要的LocalDate, LocalTime, LocalDateTime, Instant都是实现相同的接口,这里以LocalDate为例分析jav

Django的rest_framework的权限组件和频率组件源码分析

前言: Django的rest_framework一共有三大组件,分别为认证组件perform_authentication,权限组件check_throttles: 我在前面的博客中已经梳理了认证组件,不知道大家有没有看懂:在这里我把认证的组件的博客地址在贴出来,不清楚的人可以看下 局部设置认证组件的博客:https://www.cnblogs.com/bainianminguo/p/10480887.html 全局设置认证组件的博客:https://www.cnblogs.com/baini

优化ListView中的网络图片加载 及 Volley库源码分析

使用适当的开源库,如Volley或者Universal ImageLoader 以Volley库为例.Volley使用了线程池来作为基础结构,主要分为主线程,cache线程和network线程. 主线程和cache线程都只有一个,而NetworkDispatcher线程可以有多个,这样能解决比并行问题.如下图: 其中左下角是NetworkDispatcher线程,大致步骤是: 1.不断从请求队列中取出请求 request = mQueue.take(); 2.发起网络请求 NetworkResp

Java中ArrayList源码分析

一.简介 ArrayList是一个数组队列,相当于动态数组.每个ArrayList实例都有自己的容量,该容量至少和所存储数据的个数一样大小,在每次添加数据时,它会使用ensureCapacity()保证容量能容纳所有数据. 1.1.ArrayList 的继承与实现接口 ArrayList继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口. public class  ArrayList<E> ex

Django框架 --CBV源码分析、restful规范、restframework框架

一.CBV源码分析 1.url层的使用CBV from app01 import views url(r'book/',views.Book.as_view()) 2.as_view方法 as_view是一个类方法,实际上是一个闭包函数(内层函数包含对外层作用域的使用) 请求来了以后,调用as_view方法,调用函数中的view方法,view方法是调用了dispatch方法 @classonlymethod def as_view(cls, **initkwargs): def view(req

利用 Django REST framework 编写 RESTful API

利用 Django REST framework 编写 RESTful API Updateat 2015/12/3: 增加 filter 最近在玩 Django,不得不说 rest_framework 真乃一大神器,可以轻易的甚至自动化的搞定很多事情,比如: 自动生成符合 RESTful 规范的 API 支持 OPTION.HEAD.POST.GET.PATCH.PUT.DELETE 根据 Content-Type 来动态的返回数据类型(如 text.json) 生成 browserable

Django CBV流程及源码分析

Django 实现视图的方法有两种,一种是FBV(function base view)即基于函数的视图,还一种高级的就是CBV(class base view),通过阅读源码你会发现它本质上还是基于FBV的.FBV的优点是用法和写法都比较简单适合刚开始学的同学使用,缺点就是不能用的面向对象的几大特性只用函数进行封装代码多的时候会显得代码很冗余,而CBV就很好的解决了这些问题.并且Django官方在后面的Django版本中加入了很多基于CBV的类,方便我们快速开发.我们先简单的看下Django在

Android中图片加载框架Glide解析2----从源码的角度理解Glide的执行流程

转载地址:http://blog.csdn.net/guolin_blog/article/details/53939176 在本系列的上一篇文章中,我们学习了Glide的基本用法,体验了这个图片加载框架的强大功能,以及它非常简便的API.还没有看过上一篇文章的朋友,建议先去阅读 Android图片加载框架最全解析(一),Glide的基本用法 . 在多数情况下,我们想要在界面上加载并展示一张图片只需要一行代码就能实现,如下所示: Glide.with(this).load(url).into(i

ABP源码分析四十六:ABP ZERO中的Ldap模块

通过AD作为用户认证的数据源.整个管理用户认证逻辑就在LdapAuthenticationSource类中实现. LdapSettingProvider:定义LDAP的setting和提供DefautValue.主要提供配置访问AD数据库的账号信息. LdapSettings/ILdapSettings:通过settingManager获取LDAP settings AbpZeroLdapModuleConfig/IAbpZeroLdapModuleConfig: 提供激活Ldap认证的配置.