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('分类或标题不符合要求')
  • 相关阅读:
    csuOJ啊 1553
    Codeforces 111B【看看自己和别人在代码能力上的差距!】
    hdu1849
    hdu 1847
    校队训练赛,同时也是HDU4497(数论:素数分解+组合数学)
    POJ 2356 (抽屉原理)
    线段树总结一【转】
    训练赛(1---5)D
    训练赛(1---5)A
    HDU1556 【树状数组】(改段求点)
  • 原文地址:https://www.cnblogs.com/wf123/p/9965684.html
Copyright © 2011-2022 走看看