zoukankan      html  css  js  c++  java
  • DRF框架

    1、RESTful规范

      1.1 REST风格:表属性状态转移

        1.1.1资源:在web中凡是有被引用的必要的都叫资源

        1.1.2 URI:统一资源标识符    URI包含URL 

        1.1.3 URL:统一资源定位符

        1.1.4 统一资源接口,不再像以前django项目中url中增删改查都分别对应一个url,而是url中只写一个名词最为代表性的

            路由,比如(只写book,不需要book_list,book_append,book_edit,book_delate),其他的功能根据HTTP请求方式

            的不同来对资源进行操作。

        1.1.5 前后端传递的是资源的表述

        1.1.6 前端展示的是资源的状态

        1.1.7 通过超链接的指引来告诉用户接下来有哪些资源状态可以进入

      1.2 核心思想:

        1.2.1 面向对象去编程,url中尽量用名词,不要用动词

        1.2.2 根据HTTP请求方式的不同对资源进行不同的操作。

      1.3 url中要体现的信息

        1.3.1 版本

        1.3.2 API

        1.3.3 过滤条件

        1.3.4 HTTPS

      1.4 返回的要求

        1.4.1 要携带状态吗

        1.4.2 返回值

            get 获取的是所有或者单挑数据

            post 返回的是新增的这条数据

            put/patch 返回的是更新的数据

            delete 返回空

        1.4.3 携带错误信息

        1.4.4 携带超链接

    2、FBV 和 CBV 的区别

        def dispatch(self, request, *args, **kwargs):
        # GET POST
        # BookView().get
        # DJango的View只做了CBV的分发
        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)

    3、下载DRF

        pip istall djangorestframwork

        在settings的APP项中注册rest_framwork

    4、APIView 和View的区别

      4.1、APIView继承了View

      4.2、重写了as_view方法,豁免了csrf 

      4.3、重新封装了request

          新的request变成了Request的实例化对象,

            request = self.initialize_request(request, *args, **kwargs)
            self.request = request

          旧的request 变成了_request

            self._request = 旧的request  

            def query_params(self):
              return self._request.GET
            def data(self):
              return post请求的数据

    5、序列化

      5.1 django实现序列化

        5.1.1 通过.values 获取到QuerySet对象 ,通过JsonResponse进行序列化。JsonResponse和HttpResponse的区别是能

          够处理date/datetime类型的数据,但都不能解决外键关系的序列化

        5.1.2 django的序列化器 serializes.seialize 能够序列化queryset,但是也不能解决外间关系的序列化

      5.2 DRF的序列化组件

        5.2.1 先声明一个序列化器,类比django中的model.py文件

        5.2.2 在视图中使用序列化器序列化queryset

        5.2.3 序列化好的数据在set_obj.data中

      5.3 对于GET请求

        5.3.1 先获取Book对象的所有信息

           book_queryset = Book.objects.all()

        5.3.2 ser_obj = BookSerializer(book_queryset,many=True) 

          如果有many=True 认为我们的queryset是一个可迭代对象,循环我们的queryset拿到每一个模型对象

          把每个模型对象的字段跟序列化器的字段进行匹配,匹配成功的进行序列化,没有匹配成功的丢弃,

          但是序列化器里的字段必须在要匹配的字段中

      5.4 对于POST请求

        5.4.1 注意序列化和反序列化不统一的字段

            id = serializers.IntegerField(required=False)      required=False表示之序列化,不进行校验

            read_only = True :表示只进行正向序列化

            write_only = True:表示只进行反向序列化

        5.4.2 视图中      

        def post(self, request):
            book_obj = request.data                     # data是post提交的数据
            ser_obj = BookSerializer(data=book_obj)
            print(type(ser_obj), ser_obj)
            if ser_obj.is_valid():
                ser_obj.save()                          # 此save不同于ORM操作中的save,此save只是单纯的调用了create方法,所以要去重写create方法,其实是create方法对数据进行了保存
                return Response(ser_obj.validated_data)
            return Response(ser_obj.errors)

        5.4.3 重写create方法

    def create(self, validated_data):
             book_obj = Book.objects.create(title=validated_data['title'],
                                            publisher_time=validated_data['publisher_time'],
                                            category=validated_data['post_category'],
                                            publisher_id=validated_data['publisher_id'],
                                            )
             book_obj.authors.add(*validated_data['author_list'])
             return book_obj

       5.5对于PUT/PATCH请求

        5.5.1在视图中

        def put(self, request, id):
            book_obj = Book.objects.filter(id=id).first()
            ser_obj = BookSerializer(instance=book_obj, data=request.data, partial=True)
            if ser_obj.is_valid():
                ser_obj.save()                                 # 在put中,save()的时候需要重写update方法     
                return Response(ser_obj.validated_data)
            return Response(ser_obj.errors)

        5.5.2重写的update

        def update(self, instance, validated_data):
            # instance 更新的book_obj 对象
            # validated_data 校验通过的数据
            # ORM做更新操作
            instance.title = validated_data.get("title", instance.title)        #字典.get取值的时候即使没有也不会报错
            instance.pub_time = validated_data.get("pub_time", instance.pub_time)
            instance.category = validated_data.get("post_category", instance.category)
            instance.publisher_id = validated_data.get("publisher_id", instance.publisher_id)
            if validated_data.get("author_list"):
                instance.authors.set(validated_data["author_list"])
            instance.save()
            return instance

      6.1验证

        6.1.1局部钩子函数

        def validate_title(self, value):           # 局部钩子需要传value作为参数
            print(2222)
            # value就是title的值 对value处理
            if "python" not in value.lower():
                raise serializers.ValidationError("标题必须含有python")
            return value

        6.1.2全局钩子函数

        def validate(self, attrs):        # 全局钩子,需要传参数attrs 
            print(33333)
            # attrs 字典有你传过来的所有的字段
            print(attrs)
            if "python" in attrs["title"].lower() or attrs["post_category"] == 1:
                return attrs
            else:
                raise serializers.ValidationError("分类或标题不合符要求")

        6.1.3自定义验证函数

    def my_validate(value):                 # 自定义的函数,没有self,把value作为参数
        print(1111)
        if "敏感信息" in value.lower():
            raise serializers.ValidationError("有敏感词汇")
        return value
    # 对于自定义的函数,需要在序列化器中的字段中加入validators=[my_validate,]
    # title = serializers.CharField(max_length=32, validators=[my_validate,])

        6.1.4 验证的钩子函数,优先级分别是    自定义 > 局部钩子 > 全局钩子

        6.1.5 普通序列化器处理正反序列化的方法

      

    from rest_framework import serializers
    from DRF_Demo.models import Book, Publisher
    from rest_framework.response import Response
    
    
    class PublisherSerializer(serializers.Serializer):
        id = serializers.IntegerField()
        name = serializers.CharField(max_length=32)
    
    
    class AuthorSerializer(serializers.Serializer):
        id = serializers.IntegerField()
        name = serializers.CharField(max_length=32)
    
    
    class BookSerializer(serializers.Serializer):
        id = serializers.IntegerField(required=False)  # required=False 只序列化不校验
        title = serializers.CharField(max_length=32)
        publisher_time = serializers.DateField()
        category = serializers.CharField(source='get_category_display', read_only=True)
    
        publisher = PublisherSerializer(read_only=True)
        authors = AuthorSerializer(many=True, read_only=True)
        post_category = serializers.IntegerField(write_only=True)          # 对于反序列化的字段名称匹配的时候,要和提交的数据的字段相同
        publisher_id = serializers.IntegerField(write_only=True)
        author_list = serializers.ListField(write_only=True)
    
        def create(self, validated_data):
            book_obj = Book.objects.create(title=validated_data['title'],
                                           publisher_time=validated_data['publisher_time'],
                                           category=validated_data['post_category'],
                                           publisher_id=validated_data['publisher_id'],
                                           )
            book_obj.authors.add(*validated_data['author_list'])
            return book_obj
    
        def update(self, instance, validated_data):
            instance.title = validated_data.get("title", instance.title)
            instance.save()
            return instance

      7.1 ModelSerializer

        7.1.1 类似于Django中的modelform,用于生成关联的模型里的所有字段   

           model=表名
           fields="__all__"/["字段名",]
           exclude=["字段名",]
           depth=1 外键关系找一层 会让外键关系字段变成read_only=True
           extra_kwargs={"字段名": {配置的属性}}      # 对于不想要正序或者反序的字段,就用extra_kwargs={'字段名':属性}}

        7.1.2 SerlizerMethodField() 对于重写的正向序列化的字段,用这个方法字段来定义

        7.1.2 示例,用ModelSerilizer方法进行正反序列化,包括校验字段

    class BookSerializer(serializers.ModelSerializer):
        # SerializerMethodField是个方法字段,需要用get_publisher_info 来定义方法
        publisher_info = serializers.SerializerMethodField(read_only=True)
        authors_info = serializers.SerializerMethodField(read_only=True)
    
        # 通过get_变量名制定方法,obj是Book对象
        def get_publisher_info(self, obj):
            publisher_obj = obj.publisher
            # return 回来的结果返回给publisher_info,然后渲染到页面上
            return {"id": publisher_obj.id, "name": publisher_obj.name}
    
        def get_authors_info(self, obj):
            authors_obj = obj.authors.all()
            return [{'id': author.id, 'name': author.name} for author in authors_obj]
    
        class Meta:
            model = Book
            fields = '__all__'
            # depth = 1  # depth 写几就是外键向下找几层,一般不要超过四层。并且会让所有外键变成read_only=True
            # extra_kwargs 是一个字典,处理序列化的字段,如果正向序列化不想要展现publisher 和authors字段,就将他设置成write_only=True
            extra_kwargs = {'publisher': {"write_only": True}, 'authors': {"write_only": True}}
            # 定义一个局部钩子函数,validate_字段名,校验title,参数要传一个value
        def validate_title(self, value):
            if 'python' not in value.lower():
                raise serializers.ValidationError('标题必须含有python')
            return value
        def validate(self,attrs):
            if 'python' in attrs["title"].lower() or attrs["authors_info.id"] == 1:
                return attrs
            else:
                raise serializers.ValidationError('分类或标题不符合要求')
  • 相关阅读:
    常用知识点集合
    LeetCode 66 Plus One
    LeetCode 88 Merge Sorted Array
    LeetCode 27 Remove Element
    LeetCode 26 Remove Duplicates from Sorted Array
    LeetCode 448 Find All Numbers Disappeared in an Array
    LeetCode 219 Contains Duplicate II
    LeetCode 118 Pascal's Triangle
    LeetCode 119 Pascal's Triangle II
    LeetCode 1 Two Sum
  • 原文地址:https://www.cnblogs.com/wf123/p/9965684.html
Copyright © 2011-2022 走看看