明霞山资源网 Design By www.htccd.com

DRF组件的用法和作用

认证

	自定义认证的类
   """
   from rest_framework.authentication import BaseAuthentication
   from rest_framework.exceptions import AuthenticationFailed
   from authapp.models import UserToken
   class MyOrderAuthentication(BaseAuthentication):
      在这里实现认证的逻辑
     def authenticate(self, request):
       token = request._request.GET.get('token')
       # 获取到token之后,需要在数据库中查找token
       obj = UserToken.objects.filter(token=token).first()
       if not obj:
         # 没有通过认证
         raise AuthenticationFailed('认证失败')
       # 返回元组( user, auth )
       return (obj.user, obj)
   """
 
  使用局部配置(在视图函数中)
   """
   class OrderView(APIView):
     # 通过authentication_classes设置认证类
     authentication_classes = [MyOrderAuthentication,]
     # 通过authentication_classes设置为空列表,就不再进行认证了
     # authentication_classes = []
   """
 
  全局配置
   """
   REST_FRAMEWORK = {
     'DEFAULT_AUTHENTICATION_CLASSES':['unitls.authentication.MyOrderAuthentication'],
   }
   """
 
  设置匿名用户
   """
   REST_FRAMEWORK = {
     'UNAUTHENTICATED_USER': lambda :"匿名用户",
     'UNAUTHENTICATED_TOKEN': lambda :'123456',
   }
   """
 
  ## 最最重要的,理清认证的源代码

权限

 自定义权限类
  """
   from rest_framework.permissions import BasePermission
   class MyOrderPermission(BasePermission):
     #自定义权限认证的类,必须要实现has_permission方法
     message = '你不是超级用户,没有权限访问'
     def has_permission(self, request, view):
     
       #Return `True` if permission is granted, `False` otherwise.
       #返回True表示有权限访问,返回False表示没有权限访问
       if request.user.user_type != 3:
         return False
       return True
  """
 
  局部使用
  """
  class OrderView(APIView):
  
     # permission_classes设置权限类
     permission_classes = [MyOrderPermission,]
     # 通过authentication_classes设置为空列表,就不再进行权限认证了
     permission_classes = []
  """
 
  全局的设定
  """
  REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES':['unitls.permission.MyOrderPermission'],
  }
  """
  
  最最重要的,理清权限认证的源代码

分页

 自定义分页类PageNumberPagination
  # 自定制分页类
  class MyPageNumberPagination(PageNumberPagination):
    """http://127.0.0.1:8000/api/userpage/"""
    # page_size每一返回多少条
    page_size = 5
    # 设置分页的参数名
    page_query_param = 'page'
    # 设置每页返回数据量的参数名
    page_size_query_param = 'pagesize'
    # 设置每页最大返回的条数
    max_page_size = 6
 
 使用
   class UsersPageView(APIView):
     
     def get(self,request,*args,**kwargs):
       # 获取表中所有用户的row(记录)
       obj = models.UserInfo.objects.all()
       #实例化分页的类
       #page_obj = PageNumberPagination()
       page_obj = MyPageNumberPagination()
       #获取分页数据
       page_data = page_obj.paginate_queryset( queryset=obj,request=request,view=self)
       # 序列化
       ser = UsersSerializer(instance=page_data,many=True)
 
       # return Response(ser.data)
       #get_paginated_response会返回上一页下一页和总条数
       return page_obj.get_paginated_response(ser.data)
 
  自定义分页类LimitOffsetPagination
  from rest_framework.pagination import LimitOffsetPagination
 
  class MyLimitOffsetPagination(LimitOffsetPagination):
    """http://127.0.0.1:8000/api/userpage/"""
    default_limit = 5
    limit_query_param = 'limit'
    offset_query_param = 'offset'
    max_limit = 7
 
  
  自定义分页类CursorPagination(会对分页参数进行加密)
  from rest_framework.pagination import CursorPagination
 
  class MyCursorPagination(CursorPagination):
    """http://127.0.0.1:8000/api/userpage/"""
    cursor_query_param = 'cursor'
    page_size = 4
    #返回数据市的排序的方式
    ordering = '-id'
    max_page_size = 8
 
   设置全局的分页
   """
     REST_FRAMEWORK = {
       'DEFAULT_PAGINATION_CLASS':'unitl.pagination.MyCursorPagination',
       'PAGE_SIZE':3
     }
   """

视图

 以前 (Django的View)
  """
    class MyView(View)
      .....
  """
 
  现在(rest_framework的APIView)
  """
    class MyView(APIView)
    .....
  """
  
  其他视图的使用
  第一个:GenericAPIView 视图的使用 (跟继承自APIViewq其实一样,只是我们在外面逻辑,
    GenericAPIView在内部c定制方法帮我们实现了)
  """
  from rest_framework.generics import GenericAPIView
  class BookinfoSeralizer(serializers.ModelSerializer):
    
    class Meta:
      model = models.BookInfo
      fields = "__all__"
  class BookView(GenericAPIView):
    # queryset: 设置获取的数据
    queryset = models.BookInfo.objects.all()
    # serializer_class: 设置序列化的类
    serializer_class = BookinfoSeralizer
    # pagination_class : 设置分页的类
    pagination_class = MyPageNumberPagination
    def get(self,request,*args,**kwargs):
      obj = self.get_queryset() #=> obj = models.BookInfo.objects.all()
      # 获取当前分页的数据
      page_data = self.paginate_queryset(obj) #=>page_obj = MyPageNumberPagination() #获取分页数据page_data = page_obj.paginate_queryset()
      # 获取序列化之后的数据
      ser = self.get_serializer(instance=page_data,many=True) #->ser = BookinfoSeralizer(instance=page_data,many=True)
      return Response(ser.data)
  """
    
   第二个:GenericViewSet 视图的如下使用,注意路由会发生变化
    """
    class BookView(GenericViewSet):
      # queryset: 设置获取的数据
      queryset = models.BookInfo.objects.all()
      # serializer_class: 设置序列化的类
      serializer_class = BookinfoSeralizer
      # pagination_class : 设置分页的类
      pagination_class = MyPageNumberPagination
      
      def list(self,request,*args,**kwargs):
        
        obj = self.get_queryset() #=> obj = models.BookInfo.objects.all()
        # 获取当前分页的数据
        page_data = self.paginate_queryset(obj) #=>page_obj = MyPageNumberPagination() #获取分页数据page_data = page_obj.paginate_queryset(
        # 获取序列化之后的数据
        ser = self.get_serializer(instance=page_data,many=True) #->ser = BookinfoSeralizer(instance=page_data,many=True)
        
        return Response(ser.data)
    """
    路由会发生变化,配置如下
    """
    url(r"bookpage/$",views.BookView.as_view({'get': 'list'}),name='bookpage')
    """
    
    第三个:ListModelMixin,CreateModelMixin,RetrieveModelMixin,
    DestroyModelMixin,UpdateModelMixin 等视图的使用
    
    """
    from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin
    from rest_framework.viewsets import GenericViewSet
    # ListModelMixin : 返回列表数据据( get请求)
    # CreateModelMixin : 新增一条数据 (Post请求)
    # RetrieveModelMixin, : 获取详情数据 (get请求)
    # DestroyModelMixin,  : 删除数据的时候 (delete)
    # UpdateModelMixin : 跟新数据的时候使用 (put)
 
    class BookView(ListModelMixin,RetrieveModelMixin,CreateModelMixin,DestroyModelMixin,UpdateModelMixin,GenericViewSet):
      # queryset: 设置获取的数据
      queryset = models.BookInfo.objects.all()
      # serializer_class: 设置序列化的类
      serializer_class = BookinfoSeralizer
      # pagination_class : 设置分页的类
      pagination_class = MyPageNumberPagination
    """
    第四个:ModelViewSet视图的使用
    ModelViewSet继承自istModelMixin,CreateModelMixin,
    RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin视图
    如果要实现最基本的增删改查功能,就直接继承自ModelViewSet
    """
    from rest_framework.viewsets import ModelViewSet
    class BookView(ModelViewSet):
      # queryset: 设置获取的数据
      queryset = models.BookInfo.objects.all()
      # serializer_class: 设置序列化的类
      serializer_class = BookinfoSeralizer
      # pagination_class : 设置分页的类
      pagination_class = MyPageNumberPagination
    """
    视图使用小总结
      只想实现简单的增删改查
        ModelViewSet
      只想增
        CreateModelMixin,GenericViewSet
      只想增删改
        CreateModelMixin,DestroyModelMixin,UpdateModelMixin,GenericViewSet
      如果视图中的业务逻辑复杂,以上都不能满足的时候,直接使用
        APIView
   #自动路由配置
   """
     from django.conf.urls import url,include
     from api import views
     from rest_framework import routers
     
     router = routers.DefaultRouter()
     router.register(r"bookpage",views.BookView,base_name='bookpage')
     
     
     urlpatterns = [
      url(r'v1/',include(router.urls)),
     ]
   """
     
  自动路由会生成四个接口
  ^api/ v1/ ^bookpage/$ [name='bookpage-list']
  ^api/ v1/ ^bookpage\.("htmlcode">
节流:
  自定义节流类
  """
  VISIT_RECORD = {}
  class VisitThrottle(object):
    def __init__(self):
      self.history = None
    def allow_request(self,request,view):
      #实现节流的逻辑
      #基于ip做节流
      # #获取用户访问的IP地址
      # ip_address = request._request.META.get('REMOTE_ADDR')
      ctime = time.time()
      # if ip_address not in VISIT_RECORD:
      #   #第一次访问的时候将访问的时间存储在字典中(ip地址为Key,访问的时间为value值)
      #   VISIT_RECORD[ip_address] = [ctime,]
      #
      # #第二次访问的时候取出访问的历史记录
      # history = VISIT_RECORD[ip_address]
      # 基于用户的节流
      username = request.user.username
      if username not in VISIT_RECORD:
        VISIT_RECORD[username] = [ctime, ]
      history = VISIT_RECORD[username]
      self.history = history
      while history and history[-1] < ctime - 10:
        #如果访问的时间记录超过60秒,就把超过60秒的时间记录移除
        history.pop()
      if len(history) < 6:
        history.insert(0,ctime)
        return True
      return False
    def wait(self):
      #一旦用户访问次数到达阀值,显示用户需要等待的时间
      ctime = time.time()
            #09:54:30  09:54:28
      return 10 - (ctime - self.history[-1])
  """
 
  局部使用
  """
    class OrderView(APIView):
      # throttle_classes设置节流类
      throttle_classes = [VisitThrottle,]
  """
      
  全局设置
  """
  REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES':['unitls.throttle.VisitThrottle'],
  }
  """
  
  使用DRF内置的限频类
  """
  from rest_framework.throttling import SimpleRateThrottle
  
  #推荐使用这种
  class VisitThrottle(SimpleRateThrottle):
    #没有登录用户,每分钟访问10次
    scope = 'logined'
    def get_cache_key(self, request, view):
    return request.user.username
  """
 
  全局设置
  """
  REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES':{
      'unlogin':'10/m',
      'logined':'3/m',
    },
    'DEFAULT_THROTTLE_CLASSES':['unitls.throttle.VisitThrottle'],
  }
  """

版本控制

	自定义版本控制类
  """
    class ParmasVersion(object):
      def determine_version(self, request, *args, **kwargs):
        version = request.query_params.get('version')
        return version
  """
 
  使用(局部)
  """
    class VersionView(APIView):
      #设置获取版本的类
      versioning_class = ParmasVersion
  """
 
  全局设置
  """
     'DEFAULT_VERSIONING_CLASS':'unitls.version.ParmasVersion',
  """
 
  使用 DRF内置的版本控制类QueryParameterVersioning(局部)
  """
    from rest_framework.versioning import QueryParameterVersioning
    class VersionView(APIView):
      #设置获取版本的类
      versioning_class = QueryParameterVersioning
  """
  
  设置文件中的配置信息
  """
    REST_FRAMEWORK = {
      'VERSION_PARAM':'version',
      'DEFAULT_VERSION':'v1',
      'ALLOWED_VERSIONS':['v1','v2'],
    }
  """
 
  全局设置
  """
    REST_FRAMEWORK = {
      'VERSION_PARAM':'version',
      'DEFAULT_VERSION':'v1',
      'ALLOWED_VERSIONS':['v1','v2'],
      'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.QueryParameterVersioning',
    }
  """
 
 
  使用 DRF内置的版本控制类URLPathVersioning(局部)
  """
    from rest_framework.versioning import URLPathVersioning
    class VersionView(APIView):
      #设置获取版本的类
      versioning_class = URLPathVersioning
    """
  
  设置文件中的配置信息
  """
    REST_FRAMEWORK = {
      'VERSION_PARAM':'version',
      'DEFAULT_VERSION':'v1',
      'ALLOWED_VERSIONS':['v1','v2'],
    }
    """
  
  全局设置
  """
    REST_FRAMEWORK = {
      'VERSION_PARAM':'version',
      'DEFAULT_VERSION':'v1',
      'ALLOWED_VERSIONS':['v1','v2'],
      'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',
    }
  """
 
  如果使用URLPathVersioning,路由格式如下
  """
    url(r"^(",VersionView.as_view(),name='vvvv')
  """
 
  #使用 DRF内置的版本控制类URLPathVersioning 反向生成url地址
  """
    #反向生成url地址 reverse
    obj = request.versioning_scheme
    url1 = obj.reverse(viewname='orders',request=request)
    
    #使用django的reverse方法反响生成url地址
    from django.urls import reverse
    url2 = reverse(viewname='orders',kwargs={'version':'v2'})
  """

解析器

因为开发人员post请求上传数据时,传递的数据类型不同,我们可能在request._request.POST中获取不到数据
 
  case1: Content-Type : application/x-www-form-urlencoded
  服务端接收到的post请求的数据格式:username=xxxxx&age=18&sex=男
  我们就可以在request._request.POST中获取到数据
  """
    class UserInfoView(APIView):
      def post(self,request,*args,**kwargs):
        username = request._request.POST.get('username')
        age = request._request.POST.get('age')
        sex = request._request.POST.get('sex')
  """
 
  case2:Content-Type:application/json
  服务端接收到的post请求的数据格式就是json数据:{"username":"xxxx","age":"18","sex":"男"}
  在request._request.POST中就获取不到数据,但是在request.body中可以拿到
  """
    class UserInfoView(APIView):
      def post(self,request,*args,**kwargs):
        import json
        data = json.loads(request.body.decode('utf8'))
        print(data)
  """
 
  DRF内置的解析器FormParser,JSONParser
  使用(局部):
  """
    from rest_framework.parsers import FormParser,JSONParser
    class UserInfoView(APIView):
      parser_classes = [FormParser,JSONParser]
      
      #这时DRF 内部代码会根据request.Content-Type和解析器支持的media_type比较
      从而选择对应的解析器
      
      def post(self,request,*args,**kwargs):
        # 如果使用JSONParser、FormParser解析数据的话
        data = request.data
        print(data)
      
  """

渲染器

 渲染器
  INSTALLED_APPS = [
           'rest_framework',
           ]
  from rest_framework.renderers import BrowsableAPIRenderer,JSONRenderer,AdminRenderer
  class BookView(ModelViewSet):
    # 设置渲染器类型
    renderer_classes = [JSONRenderer]

序列化

 Django的序列化
  """
  #django序例化方式一
  books = models.BookInfo.objects.all().values('id','bookname')
  books = list(books)
  print(type(books), books)
  self.ret['books'] = books
  #django序例化方式二
  books = models.BookInfo.objects.all()
  books = [model_to_dict(item) for item in books]
  self.ret['books'] = books
  """
 
  DRF 序列化
  第一种:继承自serializers.Serializer
  """
     class BookDetailSerializer(serializers.Serializer):
         # 正常的字段序列化
         id = serializers.IntegerField()
         bookname = serializers.CharField()
         author = serializers.CharField()
         category = serializers.IntegerField()
         bookdesc = serializers.CharField()
         
         
         # 获取枚举类型的文本是 source=get_字段名_display
         status = serializers.CharField(
           source='get_status_display'
         )
         categoryname = serializers.CharField(
           source='get_category_display'
         )
         
         # 自定义方法获取字段
         chpaters = serializers.SerializerMethodField()
         #序列化时可以自定义方法获取字段
         def get_chpaters(self,row):
           """ row - > bookinfo """
             chpaters = models.ChpaterInfo.objects.filter(book=row)
             ser = ChpaterSerializer(instance=chpaters,many=True,
                         context=self.context
                         )
             return ser.data
  """
   序列化时生成url
  """
    url = serializers.HyperlinkedIdentityField(
    view_name='chpaterdetail', lookup_field='id',
    lookup_url_kwarg='pk',
    )
  """
  注意:如果序列化类中使用HyperlinkedIdentityField生成url,那我们在序例化时添加context={'request': request}
  """
    ser = BookDetailSerializer(
    instance=obj,many=False,
    context={'request': request}
    )
  """
 
  如果出现关联关系时,获取model对像的某一个字段
  """
    bookname = serializers.CharField(source='book.bookname')
  """
 
  第二种继承自:serializers.ModelSerializer
  """
  class ChpaterDetailSerializer(serializers.ModelSerializer):
    #使用ModelSerializer进行章节详情的序列化
    bookname = serializers.CharField(source='book.bookname')
    class Meta:
      model = models.ChpaterInfo
      #fields = "__all__"
      fields = ['id','bookname']
  """
  
  DRF (序列化时)自定义方法获取数据
  """
    book = serializers.SerializerMethodField()
  """
  """
     def get_book(self,row):
       """ row - > UserInfo"""
         print('======',row.book.all())
         ser = UsersBooksSerializer(
           instance=row.book.all(),
           many=True
         )
      
         return ser.data
  """
  
  DRF depth深度的使用
  # depth会根据关联的数据不停的深入将数据获取出来(最多不超过10层)
  # depth = 1
  """
  class UsersSerializer(serializers.ModelSerializer):
    class Meta:
      model = models.UserInfo
      fields = "__all__"
      #depth会根据关联的数据不停的深入将数据获取出来(最多不超过10层)
      depth = 1
  """
 
  DRF序列化的验证功能
  """
  class UsersSerializer(serializers.ModelSerializer):
    #自定义验证错误的信息
    username = serializers.CharField(error_messages={'required':'用户名不能为空'})
    class Meta:
      model = models.UserInfo
      fields = "__all__"
  """
 
  """
  class UsersView(APIView):
    def post(self,request,*args,**kwargs):
    """DRF 序列化自带验证功能"""
      data = request.data
      #print(data)
      ser = UsersSerializer(data=data)
      if ser.is_valid(): # ser.is_valid()y验证数据的有效性
        print('验证后的数据',ser.validated_data)
        #验证后的数据正确后,保存数据至数据库
        ser.save()
      else:
        #上传数据不符合规范时ser.errors,返回错误详细
        print(ser.errors)
      return Response(data)
  """
 
  自定义字段验证规则
  """
    class UsersInfoSerializer(serializers.ModelSerializer):
    username = serializers.CharField(error_messages={'required':'用户名不能为空'})
      class Meta:
        model = models.UserInfo
        fields = "__all__"
      
      # 用户名中必须包含老王两个字,不包含则认为名字无效
      def validate_username(self,validated_value):
        print(validated_value)
        from rest_framework.exceptions import ValidationError
        if '老王' not in validated_value:
        #验证不通过,抛出异常
          raise ValidationError('用户名不合法')
        #验证通过,返回数据
        return validated_value
  """

以上就是python drf各类组件的用法和作用的详细内容,更多关于python drf组件的资料请关注其它相关文章!

标签:
python,drf组件,python,drf组件作用

明霞山资源网 Design By www.htccd.com
广告合作:本站广告合作请联系QQ:858582 申请时备注:广告合作(否则不回)
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
明霞山资源网 Design By www.htccd.com

稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!

昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。

这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。

而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?