zoukankan      html  css  js  c++  java
  • 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
     


     








    
    
    
  • 相关阅读:
    HDU 3572 Task Schedule(拆点+最大流dinic)
    POJ 1236 Network of Schools(Tarjan缩点)
    HDU 3605 Escape(状压+最大流)
    HDU 1166 敌兵布阵(分块)
    Leetcode 223 Rectangle Area
    Leetcode 219 Contains Duplicate II STL
    Leetcode 36 Valid Sudoku
    Leetcode 88 Merge Sorted Array STL
    Leetcode 160 Intersection of Two Linked Lists 单向链表
    Leetcode 111 Minimum Depth of Binary Tree 二叉树
  • 原文地址:https://www.cnblogs.com/Rivend/p/11802880.html
Copyright © 2011-2022 走看看