django restframework 初识

简介

从后台开发的角度来说,不借助restframework框架一样可以用django来写接口。但是有了restframework之后,我们用restframework会更加方便,因为这个框架帮我们做了很多事,使用这个框架来开发接口会更加便捷。restframework里面大致实现了以下功能:

  • 权限
  • 认证
  • 访问评率限制
  • 序列化
  • 路由
  • 视图
  • 分页
  • 渲染器
  • 解析器
  • 版本

CBV和FBV

首先django不存在CBV和FBV哪种方式更好的说法,它们的本质都是一样的,写在路由里都是对应一个函数,CBV的as_view其实就是返回一个view函数。

基本流程

APIView的as_view() 方法返回一个不需要csrf验证的view函数,这个view函数调用的其实就是django原生View类中的view函数,原生view函数调用的dispatch,而dispatch被APIview重写了dispatch方法

@classmethod
    def as_view(cls, **initkwargs):
        """
        Store the original class on the view function.

        This allows us to discover information about the view when we do URL
        reverse lookups.  Used for breadcrumb generation.
        """
        if isinstance(getattr(cls, 'queryset', None), models.query.QuerySet):
            def force_evaluation():
                raise RuntimeError(
                    'Do not evaluate the `.queryset` attribute directly, '
                    'as the result will be cached and reused between requests. '
                    'Use `.all()` or call `.get_queryset()` instead.'
                )
            cls.queryset._fetch_all = force_evaluation

        view = super(APIView, cls).as_view(**initkwargs)
        view.cls = cls
        view.initkwargs = initkwargs

        # Note: session based authentication is explicitly CSRF validated,
        # all other authentication is CSRF exempt.
        return csrf_exempt(view)

原生view,在外部是一个classonlymethod, 内部通过cls(**initkwargs)创建实例

        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)

APIView的dispatch

    def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        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

restframework的全局配置

APIView有一些默认配置

renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
    content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
    metadata_class = api_settings.DEFAULT_METADATA_CLASS
    versioning_class = api_settings.DEFAULT_VERSIONING_CLASS

其中api_settings是一个对象 api_settings = APISettings(None, DEFAULTS, IMPORT_STRINGS)
其中DEFAULTS 是配置文件中的一个大字典,这个对象的实例方法如下

    def __init__(self, user_settings=None, defaults=None, import_strings=None):
        if user_settings:
            self._user_settings = self.__check_user_settings(user_settings)
        self.defaults = defaults or DEFAULTS
        self.import_strings = import_strings or IMPORT_STRINGS
        self._cached_attrs = set()

api_settings 对象只有_user_settings, defaults,import_strings 和 _cached_attrs 四个属性,当取不是这4个属性的时候调用__getattr__方法

@property
    def user_settings(self):
        if not hasattr(self, '_user_settings'):
            self._user_settings = getattr(settings, 'REST_FRAMEWORK', {})
        return self._user_settings

    def __getattr__(self, attr):
        if attr not in self.defaults:
            raise AttributeError("Invalid API setting: '%s'" % attr)

        try:
            # Check if present in user settings
            val = self.user_settings[attr]
        except KeyError:
            # Fall back to defaults
            val = self.defaults[attr]

        # Coerce import strings into classes
        if attr in self.import_strings:
            val = perform_import(val, attr)

        # Cache the result
        self._cached_attrs.add(attr)
        setattr(self, attr, val)
        return val

从上面代码来看,是先取我们django settings中的 REST_FRAMEWORK 中的内容,取不到就去DEFAULTS这个大字典去取,所以当我们去做django restframework中的全局配置就是去django settings中配置一个key为REST_FRAMEWORK的大字典。

对request的封装

django restframework中对原生request进行了封装


取GET请求的数据,三种方式:

  1. request._request.GET.get('name')
  2. request.GET.get('name')
  3. request.query_params.get('name')


posted @ 2018-07-29 15:07  龙云飞谷  阅读(264)  评论(0编辑  收藏  举报