zoukankan      html  css  js  c++  java
  • Drf06 /drf总结

    Drf06 /drf总结

    1. restful规范

    restful是一套规则,是程序间进行数据传输的一种约定
    1.建议用https代替http,为了保证数据的安全
    2.在url中添加api标识,这样看到url就知道是一个api,建议放在域名后面,这样不会存在跨域问题
    3.在接口中体现版本信息,方便于版本的迭代,
    4.restful也称面向资源编程,视网上的一切都是资源,所以一般资源都用名词
    5.如果要添加一些筛选条件,可以写在url中
    6.根据method不同做不同的操作
    7.返回给用户状态码
    8.对不同请求返回不同的数据
    9.如果有异常返回错误信息
    10.对于下一个请求要返回一个接口
    

    2. drf组件认证的实现过程?

    1.当用户请求过来时,执行dispatch,通过initialize_request方法,
    2.找到认证的所有类并实例化成对象列表,然后将对象列表封装到新的request对象中。
    3.执行下面的initial方法,经过认证的request.user方法
    4.在内部会循环认证的对象列表,并执行每个对象的authenticate方法,该方法用于认证,返回值有三种,①抛出异常②返回None③返回一个元组
    5.返回元组的两个值分别赋值给request.user和request.auth
    

    3. drf组件中权限的实现过程?

    1.当用户请求过来时,先执行dispatch方法,通过initial方法执行check_permissions方法
    2.找到权限的所有类并实例化成对象列表
    3.循环该实例化对象列表,执行每个对象的has_permission方法
    4.返回True和False进行权限的认证,可定制错误信息
    

    4. drf组件中节流的实现方式?

    - 实现原理
        来访问时:
            1.获取当前时间 100121280
            2.100121280-60 = 100121220,小于100121220所有记录删除
            3.判断1分钟以内已经访问多少次了? 4 
            4.无法访问
        停一会
        来访问时:
            1.获取当前时间 100121340
            2.100121340-60 = 100121280,小于100121280所有记录删除
            3.判断1分钟以内已经访问多少次了? 0
            4.可以访问
    - 具体流程
    	请求来时会执行allow_follow方法,
        会用self.key获取请求用户的ip,再用self.history根据用户的ip获取其访问的记录,
        获取当前的时间,用当前的时间减去设定的时间段,
        循环该用户访问的记录,将不在该时间段的记录pop掉,
        通过len判定该时间段已经访问了多少次,超过限定次数会返回false
        匿名用户是通过ip进行访问限制,登录用户通过用户的id进行访问限制
    

    5. 什么是jwt?优势?

    一般用于做用户认证(登录)使用的技术。
    jwt的实现原理:
    	- 用户登录成功之后,会给前端返回一段token。
    	- token是由.分割的三段组成。
    		- 第一段:类型和算法信息 -- header
    		- 第二段:用户信息+超时时间 -- payload
    		- 第三段:hs256(前两段拼接)加密 + base64url -- sign
    	- 以后前端再次发来信息时
    		- 超时验证
    		- token合法性校验
    优势:
    	- token只在前端保存,后端只负责校验。
    	- 内部集成了超时时间,后端可以根据时间进行校验是否超时。
    	- 由于内部存在hash256加密,所以用户不可以修改token,只要一修改就认证失败。
    

    6.drf框架

    drf是一个基于django开发的组件,本质是一个django的app。
    drf可以为我们快速开发出一个遵循restful规范的程序。
    1.drf为我们提供了一大堆视图,ListAPIView,RetrieveAPIView,DestroyAPIView,UpdateAPIView,CreateAPIView,可以帮我们快速的进行增删改查,但是只能完成最基本的对表格的增删改查,想要更多的功能可以重写视图的方法
    2.版本的处理
    3.认证
    4.权限
    5.截流(频率限制)
    6.视图过后进入解析器,有request.data,reqeust.querysetparams.get('pk')
    7.序列化,可以对用户数据进行校验以及序列化
    8.筛选器
    9.分页
    10.渲染
    

    7.写视图的方法

    • 第一种:原始APIView

      url(r'^login/$',account.LoginView.as_view()),
      
      from rest_framework.views import APIView
      from rest_framework.response import Response
      from rest_framework_jwt.settings import api_settings
      from rest_framework.throttling import AnonRateThrottle
      from api import models
      
      
      class LoginView(APIView):
          authentication_classes = []
          def post(self,request,*args,**kwargs):
              # 1.根据用户名和密码检测用户是否可以登录
              user = models.UserInfo.objects.filter(username=request.data.get('username'),password=request.data.get('password')).first()
              if not user:
                  return Response({'code':10001,'error':'用户名或密码错误'})
      
              # 2. 根据user对象生成payload(中间值的数据)
              jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
              payload = jwt_payload_handler(user)
      
              # 3. 构造前面数据,base64加密;中间数据base64加密;前两段拼接然后做hs256加密(加盐),再做base64加密。生成token
              jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER
              token = jwt_encode_handler(payload)
              return Response({'code': 10000, 'data': token})
      
    • 第二种:ListApiView等

      url(r'^article/$',article.ArticleView.as_view()),
      url(r'^article/(?P<pk>d+)/$',article.ArticleDetailView.as_view()),
      
      from rest_framework.throttling import AnonRateThrottle
      from rest_framework.response import Response
      from rest_framework.generics import ListAPIView,RetrieveAPIView
      from api import models
      from api.serializer.article import ArticleSerializer,ArticleDetailSerializer
      
      class ArticleView(ListAPIView):
          authentication_classes = []
          # throttle_classes = [AnonRateThrottle,]
      
          queryset = models.Article.objects.all()
          serializer_class = ArticleSerializer
      
      class ArticleDetailView(RetrieveAPIView):
          authentication_classes = []
          queryset = models.Article.objects.all()
          serializer_class = ArticleDetailSerializer
      
    • 第三种:

      url(r'^article/$',article.ArticleView.as_view({"get":'list','post':'create'})),
          url(r'^article/(?P<pk>d+)/$',article.ArticleView.as_view({'get':'retrieve','put':'update','patch':'partial_update','delete':'destroy'}))
      
      from rest_framework.viewsets import GenericViewSet
      from rest_framework.mixins import ListModelMixin,RetrieveModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin
      from api.serializer.article import ArticleSerializer,ArticleDetailSerializer
      
      class ArticleView(GenericViewSet,ListModelMixin,RetrieveModelMixin,CreateModelMixin,UpdateModelMixin,DestroyModelMixin):
          authentication_classes = []
          throttle_classes = [AnonRateThrottle,]
      
          queryset = models.Article.objects.all()
          serializer_class = None
      
          def get_serializer_class(self):
              pk = self.kwargs.get('pk')
              if pk:
                  return ArticleDetailSerializer
              return ArticleSerializer
      
      

    drf 相关知识点梳理

    1. 装饰器

      def outer(func):
          def inner(*args,**kwargs):
              return func(*args,**kwargs)
          return inner
      
      @outer
      def index(a1):
          pass
      
      index()
      
      def outer(func):
          def inner(*args,**kwargs):
              return func(*args,**kwargs)
          return inner
      
      def index(a1):
          pass
      
      index = outer(index)
      
      index()
      
    2. django中可以免除csrftoken认证

      from django.views.decorators.csrf import csrf_exempt
      from django.shortcuts import HttpResponse
      
      @csrf_exempt
      def index(request):
          return HttpResponse('...')
      
      # index = csrf_exempt(index)
      
      urlpatterns = [
          url(r'^index/$',index),
      ]
      
      urlpatterns = [
          url(r'^login/$',account.LoginView.as_view()),
      ]
      
      class APIView(View):
          @classmethod
          def as_view(cls, **initkwargs):
              view = super().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)
      
    3. 面向对象中基于继承+异常处理来做的约束

      class BaseVersioning:
          def determine_version(self, request, *args, **kwargs):
              raise NotImplementedError("must be implemented")
              
      class URLPathVersioning(BaseVersioning):
      	def determine_version(self, request, *args, **kwargs):
              version = kwargs.get(self.version_param, self.default_version)
              if version is None:
                  version = self.default_version
      
              if not self.is_allowed_version(version):
                  raise exceptions.NotFound(self.invalid_version_message)
              return version
      
      
    4. 面向对象封装

      class Foo(object):
      	def __init__(self,name,age):
      		self.name = name
      		self.age = age 
      		
      obj = Foo('汪洋',18)
      
      
      class APIView(View):
          def dispatch(self, request, *args, **kwargs):
      
              self.args = args
              self.kwargs = kwargs
              request = self.initialize_request(request, *args, **kwargs)
              self.request = request
      		...
              
      	def initialize_request(self, request, *args, **kwargs):
              """
              Returns the initial request object.
              """
              parser_context = self.get_parser_context(request)
      
              return Request(
                  request,
                  parsers=self.get_parsers(),
                  authenticators=self.get_authenticators(), # [MyAuthentication(),]
                  negotiator=self.get_content_negotiator(),
                  parser_context=parser_context
              )
      
      
    5. 面向对象继承

      class View(object):
         	pass
      
      class APIView(View):
          def dispatch(self):
              method = getattr(self,'get')
              method()
      
      class GenericAPIView(APIView):
          serilizer_class = None
          
          def get_seriliser_class(self):
              return self.serilizer_class
      
      class ListModelMixin(object):
          def get(self):
              ser_class = self.get_seriliser_class()
              print(ser_class)
      
      class ListAPIView(ListModelMixin,GenericAPIView):
          pass
      
      class UserInfoView(ListAPIView):
          pass
      
      
      view = UserInfoView()
      view.dispatch()
      
      
      class View(object):
         	pass
      
      class APIView(View):
          def dispatch(self):
              method = getattr(self,'get')
              method()
      
      class GenericAPIView(APIView):
          serilizer_class = None
          
          def get_seriliser_class(self):
              return self.serilizer_class
      
      class ListModelMixin(object):
          def get(self):
              ser_class = self.get_seriliser_class()
              print(ser_class)
      
      class ListAPIView(ListModelMixin,GenericAPIView):
          pass
      
      class UserInfoView(ListAPIView):
          serilizer_class = "汪洋"
      
      
      view = UserInfoView()
      view.dispatch()
      
      
      class View(object):
         	pass
      
      class APIView(View):
          def dispatch(self):
              method = getattr(self,'get')
              method()
      
      class GenericAPIView(APIView):
          serilizer_class = None
          
          def get_seriliser_class(self):
              return self.serilizer_class
      
      class ListModelMixin(object):
          def get(self):
              ser_class = self.get_seriliser_class()
              print(ser_class)
      
      class ListAPIView(ListModelMixin,GenericAPIView):
          pass
      
      class UserInfoView(ListAPIView):
          
          def get_seriliser_class(self):
              return "咩咩"
      
      view = UserInfoView()
      view.dispatch()
      
      
    6. 反射

      class View(object):
      	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)
      
      
    7. 发送ajax请求

      $.ajax({
      	url:'地址',
      	type:'GET',
      	data:{...},
      	success:function(arg){
      		console.log(arg);
      	}
      })
      
      
    8. 浏览器具有 "同源策略的限制",导致 发送ajax请求 + 跨域 存在无法获取数据。

      • 简单请求,发送一次请求。
      • 复杂请求,先options请求做预检,然后再发送真正请求
      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <title>Title</title>
      </head>
      <body>
          <h1>常鑫的网站</h1>
          <p>
              <input type="button" value="点我" onclick="sendMsg()">
          </p>
          <p>
              <input type="button" value="点他" onclick="sendRemoteMsg()">
          </p>
      
        
          <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
          <script>
              function sendMsg() {
                  $.ajax({
                      url:'/msg/',
                      type:'GET',
                      success:function (arg) {
                          console.log(arg);
                      }
                  })
              }
              function sendRemoteMsg() {
                  $.ajax({
                      url:'http://127.0.0.1:8002/json/',
                      type:'GET',
                      success:function (arg) {
                          console.log(arg);
                      }
                  })
      
              }
          </script>
      </body>
      </html>
      
      
      
    9. 如何解决ajax+跨域?

      CORS,跨站资源共享,本质:设置响应头。
      
      
    10. 常见的Http请求方法

      get
      post
      put
      patch
      delete
      options
      
      
    11. http请求中Content-type请起头

      情况一:
          content-type:x-www-form-urlencode
          name=alex&age=19&xx=10
      	
      	request.POST和request.body中均有值。
      	
      情况二:
      	content-type:application/json
          {"name":"ALex","Age":19}
          
          request.POST没值
          request.body有值。
      
      
    12. django中F查询

    13. django中获取空Queryset

      models.User.object.all().none()
      
      
      
    14. 基于django的fbv和cbv都能实现遵循restful规范的接口

      def user(request):
          if request.metho == 'GET':
              pass
          
          
      class UserView(View):
          def get()...
          
          def post...
      
      
      
    15. 基于django rest framework框架实现restful api的开发。

      - 免除csrf认证
      - 视图(APIView、ListAPIView、ListModelMinx)
      - 版本
      - 认证
      - 权限
      - 节流
      - 解析器
      - 筛选器
      - 分页
      - 序列化
      - 渲染器
      
      
      
    16. 简述drf中认证流程?

    17. 简述drf中节流的实现原理以及过程?匿名用户/非匿名用户 如何实现频率限制?

    18. GenericAPIView视图类的作用?

      他提供了一些规则,例如:
      
      class GenericAPIView(APIView):
          serializer_class = None
          queryset = None
          lookup_field = 'pk'
          
          filter_backends = api_settings.DEFAULT_FILTER_BACKENDS
          pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
          
          def get_queryset(self):
              return self.queryset
          
          def get_serializer_class(self):
              return self.serializer_class
          
      	def filter_queryset(self, queryset):
              for backend in list(self.filter_backends):
                  queryset = backend().filter_queryset(self.request, queryset, self)
              return queryset
          
          @property
          def paginator(self):
              if not hasattr(self, '_paginator'):
                  if self.pagination_class is None:
                      self._paginator = None
                  else:
                      self._paginator = self.pagination_class()
              return self._paginator
          
      他相当于提供了一些规则,建议子类中使用固定的方式获取数据,例如:
      class ArticleView(GenericAPIView):
          queryset = models.User.objects.all()
          
          def get(self,request,*args,**kwargs):
              query = self.get_queryset()
      
      我们可以自己继承GenericAPIView来实现具体操作,但是一般不会,因为更加麻烦。
      而GenericAPIView主要是提供给drf内部的 ListAPIView、Create....
      class ListModelMixin:
          def list(self, request, *args, **kwargs):
              queryset = self.filter_queryset(self.get_queryset())
      
              page = self.paginate_queryset(queryset)
              if page is not None:
                  serializer = self.get_serializer(page, many=True)
                  return self.get_paginated_response(serializer.data)
      
              serializer = self.get_serializer(queryset, many=True)
              return Response(serializer.data)
          
      class ListAPIView(mixins.ListModelMixin,GenericAPIView):
          def get(self, request, *args, **kwargs):
              return self.list(request, *args, **kwargs)
      
      class MyView(ListAPIView):
          queryset = xxxx 
          ser...
      
      
      
      总结:GenericAPIView主要为drf内部帮助我们提供增删改查的类LIstAPIView、CreateAPIView、UpdateAPIView、提供了执行流程和功能,我们在使用drf内置类做CURD时,就可以通过自定义 静态字段(类变量)或重写方法(get_queryset、get_serializer_class)来进行更高级的定制。
      
      
      
    19. jwt以及其优势。

    20. 序列化时many=True和many=False的区别?

      many=True 序列化多个数据
      many=False 序列化单个数据
      
      
    21. 应用DRF中的功能进行项目开发

      *****
      	解析器:request.query_parmas/request.data
      	视图
      	序列化
      	渲染器:Response
      
      ****
      	request对象封装
      	版本处理
      	分页处理
      ***
      	认证
      	权限
      	节流
      
      
      
      • 基于APIView实现呼啦圈
      • 继承ListAPIView+ GenericViewSet,ListModelMixin实现呼啦圈
    22. jwt和传统的token的区别?

     # 补充
     传统的token会放在缓冲中,redis缓冲中,实际上不会放在数据库
    
  • 相关阅读:
    项目开发基础概念
    django 对接elasticsearch实现全文检索
    win10安装docker
    Mac VMware Fusion 中修改 centos7 虚拟机的磁盘空间、扩容
    CentOS 7下 YUM 本地仓库的搭建
    mac与虚拟机传输文件
    mac和windows快速锁定电脑
    rpm -qa详解
    虚拟机安装centos6
    mac与iPhone互传文件
  • 原文地址:https://www.cnblogs.com/liubing8/p/11853622.html
Copyright © 2011-2022 走看看