• Django源码分析rest_framework 关于re_path('^publish/', views.PublishView.as_view()总结


     1. ApiView
    
    定义一个cbc视图
    
    class BookView (APIView):pass
    
    re_path(r"books/$", views.BookView.as_view(),name = "books"),
    
    re_path(r"books/$", views.类下的View.as_view(),name = "books"),
    
    一单有请求进来访问books/:  view(request) ========APIView 类下的dispatch( )执行
    
     
    
    2.def dispatch():
    
      # 初始化操作
    
      ( 1 )构造新的request: 
    
         self.request = self.initial_request( )  
    
      # self.request._request
    
      # self.request.GET
    
      # self.reqeust.data
    
      ( 2 ) 执行组件
    
        # 认证,权限,频率
    
      认证 : request.user
    
        self.initial (request, *args , **kwargs)
    
        # 认证组件,他调用了新创建的request.user方法
        self.perform_authentication(request)
          认证:request.user
          self.initial(request,*args,**kwargs)
            ========# 认证组件
                self.perform_authentication(request)
                    request.user
                      ========
                           for authenticator in self.authenticators: {# toekn}
            # 我取了self.authenticators 中的一个属性
            for authenticator in self.authenticators: # [TokenAuth()]执行的返回值
                try:
                    # 意思就是你如果没有自定义这个类就会抛错
                    user_auth_tuple = authenticator.authenticate(self)# 我自定义的这个方法
                except exceptions.APIException:
                    self._not_authenticated()
                    """
                    有异常了 可以用rasie决定异常了该做什么
                    不过 即使没有异常 也可以raise来定义满足特定条件后抛弃什么异常
                    """
                    raise
                # 这个条件成立
                if user_auth_tuple is not None:
                    self._authenticator = authenticator # 赋值 [TokenAuth()]
                    # <rest_framework.request.Request object at 0x036BC390>
                    self.user, self.auth = user_auth_tuple  # 自定义方法的返回值 赋值了给 user, auth
                    return
    
    
        # 权限组件
        self.check_permissions(request)
          ========
                    
            # 这里我for循环了一个方法,这个方法就是我定义的那个类
            for permission in self.get_permissions():
                # <rest_framework.permissions.AllowAny object at 0x034F1810>
              # 我们得确认下 permission.has_permission(request, self) 发生了什么
                if not permission.has_permission(request, self):
                    self.permission_denied(
                        request, message=getattr(permission, 'message', None)
                    )
    
    
    

            
        
    # 频率组件     self.check_throttles(request)   (3)分发:     # Get the appropriate handler method   if request.method.lower() in self.http_method_names: # self = Publish,反射类中的get方法如果有我就封装到handler里面,如果你没有定义方法我我也就返回一个错误信息    handler = getattr(self, request.method.lower(), self.http_method_not_allowed)   else:   handler = self.http_method_not_allowed # 也就是说这个地方要么就是调用我Publish的get方法和post方法,要不就抛错误信息   response = handler(request, *args, **kwargs)

    4.序列化组件
    1.
    serializers.Serializer 初级版
    from django.shortcuts import render, HttpResponse, redirect
    from django.views import View
    from app01 import models
    from rest_framework.views import APIView
    
    # 一.定义一个反序列的类
    from rest_framework import serializers
    from rest_framework.response import Response
    
    
    # 为queryset, model对象做序列化,只要你定义了name和addr我都能给你反序列化 class PublishSerializers(serializers.Serializer):    name = serializers.CharField()    addr = serializers.CharField()
    #使用
    class PublishView(APIView):
        # 查询数据
        def get(self, request):
            # first inquire database
            publish = models.Publisher.objects.all()
            # data put serializers data packging
            bs = PublishSerializers(publish, many=True)  # many=True多个对象
            # return
            return Response(bs.data)
    
    # 一对多 多对多的使用
    class BookSerializers(serializers.Serializer):
        title = serializers.CharField()
        pub_date = serializers.DateField()
        # 反序列化一对多字段返回的是__str__数据
        publish = serializers.CharField(source="publish.addr")  # source 可以指定返回的一对多的字段
        # authors=serializers.CharField(source="authors.all")  # 指定序列化多对多的字段
        authors = serializers.SerializerMethodField()
    
        # 多对多字段序列化方法,这个函数必须是get_authors,因为这个字段在是多对多
        def get_authors(self, obj):
            temp = []
            for obj in obj.authors.all():
                temp.append(obj.name)
            return temp
    #使用
    class PublishView(APIView):
        # 查询数据
        def get(self, request):
            # first inquire database
            book = models.Book.objects.all()
            # data put serializers data packging
            bs = BookSerializers(book, many=True)  # many=True多个对象
            # return
            return Response(bs.data)
        bs = PublishModelSerializers(data=request.data, many=True)  # post不需要定义many=Ture
    
            if bs.is_valid():
                bs.save()  # 保存

    # 更多操作

            ps = PublishModelSerializers(publish, data=request.data)
            # if ps pass verify
            if ps.is_valid():
                ps.save() #更新
    
    
    2.serializers.ModelSerialize 中级版
    class BookModelSerializers(serializers.ModelSerializer):
        # 自定义publish字段超链接路径
        # publish_url = serializers.HyperlinkedIdentityField(view_name='detailpublish',
        #                                                    lookup_field='publish_id',
        #                                                    lookup_url_kwarg='pk',
        #                                                    )
        # publish = serializers.CharField(source="publish.id")
        """
        # view_name参数 进行传参的时候是参考路由匹配中的name与namespace参数
        #  lookeup_field参数是根据在UserInfo表中的连表查询字段group_id
        # look_url_kwarg参数在做url反向解析的时候会用到
        """
    
        #  重写save中的create方法
        # def create(self, validated_data):
        #     # create 方法之前也可以单独pop在添加
        #     """
        #     author = validated_data.pop[title]
        #     然后再进行额外自己添加
        #     obj = Book.objecte.create(**validated_data)
        #     obj.authors.add(*authors)
        #     """
        #     publish_id = validated_data["publish"]["id"]
        #     book = models.Book.objects.create(title=validated_data["title"], pub_date=validated_data["pub_date"],
        #                                       publish=models.Publisher.objects.filter(pk=publish_id).first()
        #                                       )
        #     book.authors.add(*validated_data["authors"])
        #     return book
    
        class Meta:
            model = models.Book
            # fields = ['id', 'title', 'pub_date', 'publish', 'authors']
            fields = "__all__"
            depth = 0  ## 0 ~ 10
            # 自动向内部进行深度查询,就是查询的比较详细  depth表示查询层数
    
    
    5.视图组件

    from rest_framework import serializers
    from rest_framework.response import Response
    from rest_framework import viewsets
    from django.views import View
    from app01 import models
    from rest_framework.views import APIView

    # 版本1:
    class PublishDetaiView(APIView):
        # 将这个pk设置成和lookup_url_kwarg='pk' 一样的值,不然加后缀会取不到值
        def get(self, request, id):  # id 不要放到request前面
            # 查询数据库
            publish = models.Publisher.objects.filter(pk=id)
            # 封装打包序列化数据
            bs = PublishModelSerializers(publish, many=True)  # many=True多个对象
            # Response 会直接返回josn数据格式
            ret = Response(bs.data)
    
            return ret
    
        # #  修改数据(前端指定id值后,在data中输入k:v即可change数据)
        def put(self, request, id):
            # inquire database
            publish = models.Publisher.objects.filter(pk=id).first()
            # data=  form request.data client
            ps = PublishModelSerializers(publish, data=request.data)
            # if ps pass verify
            if ps.is_valid():
                ps.save()
                return Response(ps.data)
            else:
                return Response(ps.errors)
    
        # 删除数据(功能还未实现)
        def delete(self, request, id):
            print(type(id), 5555555555555)
            models.Publisher.objects.filter(id=id).delete()
            return Response("删除成功")
    
    

    # 版本 2 

    class BOOK(GenericAPIView, mixins.ListModelMixin):
        queryset = models.School.objects.all()
        serializer_class = app01_serializers.SchoolSerializer
    
        def get(self, request, *args, **kwargs):
            return self.list(request, *args, **kwargs)
    
    
    class BOOK(GenericAPIView, mixins.RetrieveModelMixin, mixins.CreateModelMixin):
        queryset = models.School.objects.all()
        serializer_class = app01_serializers.SchoolSerializer
    
        def get(self, request, pk, *args, **kwargs):
            return self.retrieve(request, pk, *args, **kwargs)
    
        def post(self, request, *args, **kwargs):
            return self.create(request, *args, **kwargs

    # 版本3 基于通用类

    # 封装了3层
    class AuthorView(viewsets.ModelViewSet):
        # queryset serializer 这两个方法一定要定义成这个不然取不到值
        queryset = models.Author.objects.all()
        serializer_class = AuthorModelSerializers
    
    
    # 封装了3层
    class AuthorDetaiView(viewsets.ModelViewSet):
        # authentication_classes = [TokenAuth]
        # queryset serializer 这两个方法一定要定义成这个不然取不到值
        queryset = models.Author.objects.all()
        serializer_class = AuthorModelSerializers

    # 版本四

        re_path('^authors/$', views.AuthorView.as_view({"get": "list", "post": "create"})),
        # View(request) ======APIView:dispatch()
        re_path('^author/(?P<pk>d+)/$',
                views.AuthorDetaiView.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),

      流程:

        请求一旦访问/authors/:

        View()

                # Bind methods to actions
                # This is the bit that's different to a standard view
                for method, action in actions.items():
                    handler = getattr(self, action)  # self.list  self.creat
                    setattr(self, method, handler)  # self.get    self.post
            return self.dispatch(request, *args, **kwargs)

              APIView 类下的self.dispatch

               #分发 执行视图
                # Get the appropriate handler method
                if request.method.lower() in self.http_method_names:
                    # self = Publish,反射类中的get方法如果有我就封装到handler里面,如果你没有定义方法我我也就返回一个错误信息
                    handler = getattr(self, request.method.lower(),
                                      self.http_method_not_allowed)
                else:
                    handler = self.http_method_not_allowed
                    # 也就是说这个地方要么就是调用我Publish的get方法和post方法,要不就抛错误信息
    
                response = handler(request, *args, **kwargs)
            return self.response


    6.认证频率组件
    import time
    
    # 自定义限制
    VISIT_RECORD = {}
    class VisitRateThrottle(object):
        def __init__(self):
            self.history = None
    
        def allow_request(self, request, view):
    
            """
            自定义频率限制60秒内只能访问三次
            """
            # 获取用户IP
            ip = request.META.get("REMOTE_ADDR")
            # 获取当前时间戳
            timestamp = time.time()
    
            # 如果当前访问ip没有在列表中 我就新建一个IP访问记录
            if ip not in VISIT_RECORD:
                VISIT_RECORD[ip] = [timestamp, ]
                # 可以通过验证
                return True
    
            # 如果列表中有值,我就取当当前ip地址 赋值给变量
            history = VISIT_RECORD[ip]
            self.history = history
            # 在列表头部 插入一个时间戳
            history.insert(0, timestamp)
            # 如果列表有值,最先插入的值小于 当前值-60 ,tiemstamp是当前时间是在增加的
            while history and history[-1] < timestamp - 60:
                # pop 取出 最后一个条件成立的值
                history.pop()
            # 列表中的时间戳 大于3 就返回falsse,否则通过
            if len(history) > 3:
                return False
            else:
                return True
    
        def wait(self):
            # 返回给前端还剩多少时间可以访问
            timestamp = time.time()
            # 求出还剩多少时间可以访问
            return 60 - (timestamp - self.history[-1])
    7.解析器 和渲染器
    from rest_framework.parsers import JSONParser,FormParser,MultiPartParser,FileUploadParser
    parser_classes = [JSONParser,FormParser]

    8,解析器(路由控制)
    针对:
        
    re_path(r'^authors/$', views.AuthorModelView.as_view({"get":"list","post":"create"}),name="author"),
    re_path(r'^author/(?P<pk>d+)/$', views.AuthorModelView.as_view({"get":"retrieve","put":"update","delete":"destroy"}),name="detailauthor"),
    class AuthorModelView(viewsets.ModelViewSet):
       queryset = Author.objects.all()
    serializer_class = AuthorModelSerializers
     


     








    
    
    
  • 相关阅读:
    关于Openfeint + xcode 4.2 不能编译的解决方案
    CocoaAsyncSocket
    IDEA快捷键
    在升级了ADT22之后报java.lang.NoClassDefFoundError错误
    关于Toast连点显示不及时的问题
    在使用ListFragment的setEmptyText时报java.lang.IllegalStateException: Can't be used with a custom content view错误
    推荐系统专题
    Javascript 排序(转)
    js进阶
    JavaScript之定时器性能优化
  • 原文地址:https://www.cnblogs.com/Rivend/p/11802880.html
Copyright © 2020-2023  润新知