DRF 序列化

Django REST framework序列化

Django REST framework(DRF)框架文档齐全,社区较稳定,而且由于它是基于Django这个十分全面的框架而设计开发的,能够让开发者根据自己的业务需要,使用极少的代码量快速的开发一套符合RESTful风格的API,并且还支持自动生成API文档。

Django REST framework(DRF)官网:http://www.django-rest-framework.org/

中文文档 https://q1mi.github.io/Django-REST-framework-documentation/

起步

  1. 安装

    1. pip install djangorestframework
  2. 注册APP(不是必须)

    1. INSTALLED_APPS = [
      	...,
          'rest_framework',
      ]
      
  3. 导入APIView from rest_framewor.views import APIView, CBV继承它

  4. 自己写一个序列化的工具类 BookSerializer

    1. from rest_framework import serializers
      
      
      class BookSerializer(serializers.Serializer):
          id = serializers.IntegerField(required=False)
          title = serializers.CharField(max_length=32)
          pub_date = serializers.DateField()
          CHOICES = ((1, 'Python'), (2, 'Go'), (3, 'Linux'))
          category = serializers.ChoiceField(choices=CHOICES)
      
  5. 使用queryset数据实例化得到一个 序列化对象 --》 ser_obj

  6. 使用from rest_framework.response import Response restframework提供的Respoinse`返回上一步的 ser_obj.data

    1. from rest_framework.views import APIView
      from rest_framework.response import Response
      from bms.serializer import BookSerializer
      from bms import models
      
      class BookListView(APIView):
          def get(self, request):
              """以JSON格式返回书籍的所有信息"""
              # 1. 查出所有书籍信息
              queryset = models.Book.objects.all()
              # 2. 使用serizlizer序列化
              ser_boj = BookSerializer(queryset, many=True)
              return Response(ser_boj.data)
      

序列化

Django ORM对象 ---> JSON格式的数据 序列化

JSON格式的数据 ----> Django ORM数据 反序列化

两个工具

from rest_framework.serializers import Serializer
from rest_framework.serializers import ModelSerializer

类比Django中的form组件

from作用

Django form -----》 HTML表单

HTML表单 ----》 ORM数据

参数

  1. many=True参数

    1. 序列化对象时添加,可以序列化多个对象,原理实现在APIView的 __new__方法中,循环序列化对象
  2. read_only=Truewrite_only=True

    1. read_only=True,仅序列化用
    2. ``write_only=True`,仅反序列化用
  3. source

    1. 将用于填充字段的属性的名称

    2. category = serializers.CharField(source='get_category_display', read_only=True)
      
      
      
  4. require=False

    1. 校验的时候,该字段可以不填

校验

校验规则由序列化对象的is_valid()触发

  1. 局部校验方法

        def validate_title(self, attrs):
            """类似于Form中的校验钩子"""
            # attrs就是需要检验的这个字段的值
            if '最' in attrs:
                raise serializers.ValidationError('非法字段')
            else:
                return attrs
    
    
  2. 全局校验方法

    1. def validate(self, attrs):
          """全局校验钩子"""    
          return attrs
      
  3. 自定义校验函数

    1. # 类似于Form组建中的自定义校验规则
      title = serializers.CharField(max_length=32, validators=[my_validator, ])  
      

ModelSerializer

和model一对一绑定的序列化类

  1. SerializerMethodField字段:

    1. class BookModelSerializer(serializers.ModelSerializer):
          # SerializerMethodField 会自动去找 get_字段名 的方法执行
          category_info = serializers.SerializerMethodField(read_only=True)
          publisher_info = serializers.SerializerMethodField(read_only=True)
          authors_info = serializers.SerializerMethodField(read_only=True)
      
          def get_category_info(self, book_obj):
              # book_obj ==》 当前被序列化的那个书籍对象
              return book_obj.get_category_display()
      
          def get_publisher_info(self, obj):
              return PublisherSerializer(obj.publisher).data
      
          def get_authors_info(self, obj):
              return AuthorSerializer(obj.authors.all(), many=True).data
      
          class Meta:
              model = models.Book
              fields = '__all__'
              # exclude = []  # 排除某个字段
              # depth = 1  # 所有有关系的字段都变成 read_only
              extra_kwargs = {  # 每个字段的一些额外参数
                  'publisher': {'write_only': True},
                  'authors': {'write_only': True},
                  'category': {'write_only': True},
              }
      
      

终极修改序列化 字段

如果单API需要一个字段,但在model 不存在,需要自自己加,且复杂,直接加到 to_repreentation

    def to_representation(self, instance):
        # 调用父类的同名方法把序列化的结果拿到
        data = super().to_representation(instance)
        # 针对序列化的结果做一些自定制操作
        # 判断当前这个课程是否有永久有效的价格
        price_obj = instance.price_policy.all().filter(valid_period=999).first()
        if price_obj:
            # 有永久有效的价格
            data['has_price'] = True
            data['price'] = price_obj.price
        else:
            # 没有永久有效的价格策略
            data['has_price'] = False
        return data
posted @ 2019-08-16 16:30  写bug的日子  阅读(177)  评论(0编辑  收藏  举报