Django - DRF - 框架介绍、APIview分析

12 篇文章 2 订阅

目录

一、DRF框架 - Django REST Framework

1-1 DRF框架介绍 - 官方文档

1-2 安装

二、APIview源码分析

2-1  as_view方法源码 - 返回结果局部禁用Django自带的csrf组件,触发dispatch方法的执行

2-2 dispatch - 使用APIview的dispatch进行请求分发处理,对request进行了处理

2-3 initialize_request - 返回新处理的request,既包含了原有属性又增加了相应属性

2-4 request - 对request进行处理,getattr和setattr的处理

2-4-1 __getattr__处理对DRF内request内不存在属性的请求

2-4-2 request.data  - 存储前台传输原body体内数据

2-4-3 request.query_params - 存储原始GET内数据

三、使用DRF的简单数据操作


一、DRF框架 - Django REST Framework

1-1 DRF框架介绍 - 官方文档

  Django REST框架是用于构建Web api的强大而灵活的工具包,即Django内置模块的拓展,可视为Django的第三方APP插件包。

  • Web可浏览API对于开发人员来说是一个巨大的可用性胜利。
  • 身份验证策略,包括OAuth1a和OAuth2的包。
  • 同时支持ORM和非ORM数据源的序列化。
  • 可自定义的——如果不需要更强大的功能,只需使用常规的基于功能的视图。
  • 丰富的文档和强大的社区支持。
  • 得到Mozilla、Red Hat、Heroku、Eventbrite等国际知名公司的使用和信任。

1-2 安装

  • 方式一:pip3 install djangorestframework
  • 方式二:pycharm图形化界面安装
  • 方式三:pycharm命令行下安装(装在当前工程所用的解释器下)
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',

    # 组件注册
    'rest_framework',
]

 

二、APIview源码分析

2-1  as_view方法源码 - 返回结果局部禁用Django自带的csrf组件,触发dispatch方法的执行

注意:

  • 项目的启动流程:
    • 项目启动 - urls路由内放入as_view()内存地址 - 接受请求 - 执行as_view() - 触发dispatch函数 - diaspatch进行视图函数的分发
@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.
    将原始类存储在视图函数中。这允许我们在执行URLreverse查找时发现关于视图的信息。用于生成导航。

    """
    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.
    # 局部禁用Django自带的csrf组件,返回的结果实际是一个函数的内存地址
    # 当在路由中进配置时,as_view()将内存地址放入执行
    return csrf_exempt(view)

2-2 dispatch - 使用APIview的dispatch进行请求分发处理,对request进行了处理

注意: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.

    ' .dispatch() '与Django的常规调度非常相似,
    但是有额外的钩子用于启动、finalize和异常处理。

    """
    self.args = args
    self.kwargs = kwargs
    # request参数为原始request,以及后续有名分组等传输参数
    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

2-3 initialize_request - 返回新处理的request,既包含了原有属性又增加了相应属性

def initialize_request(self, request, *args, **kwargs):
    """
    Returns the initial request object.
    返回初始请求对象。
    """
    parser_context = self.get_parser_context(request)
    
    # 类实例化产生了对象,产生新的DRF的request
    return Request(
        request,
        # 用于解析(获取解析器)
        parsers=self.get_parsers(),
        # 用于认证
        authenticators=self.get_authenticators(),
        # 用于分页
        negotiator=self.get_content_negotiator(),
        # 用于解析
        parser_context=parser_context
    )

2-4 request - 对request进行处理,getattr和setattr的处理

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.

   包装器允许增强一个标准的HttpRequest实例。
   Kwargs:
        -请求(HttpRequest)。原始请求实例。
        - parsers_classes(列表/元组)。用于解析的解析器请求的内容。
        = authentication_classes(列表/元组)。用于尝试的验证验证请求的用户。
    """

    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,)


   

2-4-1 __getattr__处理对DRF内request内不存在属性的请求

def __getattr__(self, attr):
"""
位于request类内
实现效果:若外部调用DRF内不存在的属性,会去_request查找,_request在init内被赋予原始request

If an attribute does not exist on this instance, then we also attempt
to proxy it to the underlying HttpRequest object.
如果这个实例上不存在属性,那么我们也会尝试将其代理到底层HttpRequest对象。
"""
try:
    # getattr获取self._request内attr属性的值,若找不到属性 自动返回None
    return getattr(self._request, attr)
except AttributeError:
    return self.__getattribute__(attr)

2-4-2 request.data  - 存储前台传输原body体内数据

@property
def data(self):
'''request内方法,被@property隐藏为属性使用'''
    if not _hasattr(self, '_full_data'):
        self._load_data_and_files()
    return self._full_data

2-4-3 request.query_params - 存储原始GET内数据

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

三、使用DRF的简单数据操作

from rest_framework.views import APIView
class Books(APIView):
    # rest_framework.request下的Request作为参数传入
    def put(self, request, pk):
        # django.core.handlers.wsgi.WSGIRequest----原来的djagno中的request的类
        # 现在的request已经成了:rest_framework.request.Request
        # print(request.PUT)
        # 以后再取数据,直接从request.data中取
        print(request.data)
        # 前端传过来的编码格式:json格式:{'name': '水都是', 'price': '15'}
        # 前端传过来的编码格式:urlencoded格式:<QueryDict: {'name': ['红楼梦'], 'price': ['15']}>

        # request.data是谁的对象?
        # request.data不同编码格式过来,它可能是不同类的对象,但是用法是一样的

        # 原来的request是:request._request
        print(type(request._request))
        
        # 由于__getattr__可以直接使用原有方式获取数据
        # 下列二者相同,也能取出来(method,GET,POST,BODY)
        print(request._request.GET)
        print(request.GET)

        return JsonResponse({'status': 100, 'msg': '修改成功'})

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值