一、序列化


返回

1.1 Django

  • JsonResponse实现序列化

    from django.views import View
    from django.http import jsonResponse
    
    class BookView(View):
    
        def get(self, request):
            """ 第一版 用.values JsonResponse实现序列化 """
            book_list = Book.objects.values("id", "title", "category", "pub_time", "publisher")
            book_list = list(book_list)
            ret = []
            # 只能获取到book_list中出版社的ID,详细信息需要手动拼接
            for book in book_list:
                publisher_id = book["publisher"]
                publisher_obj = Publisher.objects.filter(id=publisher_id).first()
                book["publisher"] = {
                    "id": publisher_id,
                    "title": publisher_obj.title
                }
                ret.append(book)
            # ret = json.dumps(book_list, ensure_ascii=False)
            return JsonResponse(ret, safe=False, json_dumps_params={"ensure_ascii": False})
    
    
  • Djangoserializers实现序列化

    from django.views import View
    from django.core import serializers
    
    class BookView(View):
    
        def get(self, request):
            """ 第二版 用django serializers实现序列化 """
            book_list = Book.objects.all()
            # serializers获取book_list的信息,外键依旧是ID,详细信息需手动获取
            ret = serializers.serialize("json", book_list, ensure_ascii=False)
            return HttpResponse(ret)
    
    

1.2 DRF

  • Serializer

    from rest_framework import serializers
    from .models import Book
    
    
    class PublisherSerializer(serializers.Serializer):
        """ 外键 """
        id = serializers.IntegerField()
        title = serializers.CharField(max_length=32)
    
    
    class AuthorSerializer(serializers.Serializer):
        """ 多对多 """
        id = serializers.IntegerField()
        name = serializers.CharField(max_length=32)
    
    
    def my_validate(value):
        """ 校验规则1:外部自定义。优先级比内部钩子高 """
        if "敏感信息" in value.lower():
            raise serializers.ValidationError("不能含有敏感信息")
        else:
            return value
    
    
    class BookSerializer(serializers.Serializer):
        """ Serializer """
        id = serializers.IntegerField(required=False)  # required=False,该字段不需要校验
        title = serializers.CharField(max_length=32, validators=[my_validate, ])  # validators,自定义的校验规则
        CHOICES = ((1, "Python"), (2, "Go"), (3, "Linux"))
        category = serializers.ChoiceField(choices=CHOICES, source="get_category_display", read_only=True)  # source="get_category_display",获取choices的中文
        w_category = serializers.ChoiceField(choices=CHOICES, write_only=True)
        pub_time = serializers.DateField()
    
        publisher = PublisherSerializer(read_only=True)  # read_only=True,只做展示 GET 正序列化
        publisher_id = serializers.IntegerField(write_only=True)  # write_only=True,只做校验 POST PUT 反序列化
        author = AuthorSerializer(many=True, read_only=True)  # many=True,多对多
        author_list = serializers.ListField(write_only=True)  # ListField(),列表字段
    
        def create(self, validated_data):
            """ 对于POST请求,重写create方法 """
            book = Book.objects.create(title=validated_data["title"], category=validated_data["w_category"],
                                       pub_time=validated_data["pub_time"], publisher_id=validated_data["publisher_id"])
            book.author.add(*validated_data["author_list"])  # 多对多
            return book
    
        def update(self, instance, validated_data):
            """ 对于PUT|PATCH请求,重写update方法 """
            instance.title = validated_data.get("title", instance.title)
            instance.category = validated_data.get("category", instance.category)
            instance.pub_time = validated_data.get("pub_time", instance.pub_time)
            instance.publisher_id = validated_data.get("publisher_id", instance.publisher_id)
            if validated_data.get("author_list"):
                instance.author.set(validated_data["author_list"])  # 多对多
            instance.save()
            return instance
    
        def validate_title(self, value):
            """ 校验规则2:局部钩子 """
            if "python" not in value.lower():
                raise serializers.ValidationError("标题必须含有python")  # 主动抛异常
            return value
    
        def validate(self, attrs):
            """ 校验规则3:全局钩子 """
            if attrs["w_category"] == 1 and attrs["publisher_id"] == 1:
                return attrs
            else:
                raise serializers.ValidationError("分类以及标题不符合要求")
    
    
  • ModelSerializer

    from rest_framework import serializers
    from .models import Book
    
    class BookSerializer(serializers.ModelSerializer):
        """ ModelSerializer """
        # category = serializers.CharField(source="get_category_display")  # 普通取字段
        category_display = serializers.SerializerMethodField(read_only=True)  # SerializerMethodField,用方法取字段
        publisher_info = serializers.SerializerMethodField(read_only=True)  # read_only=True,只做展示 GET 正序列化
        authors = serializers.SerializerMethodField(read_only=True)
    
        def get_category_display(self, obj):
            """ 方法字段对应的方法 """
            return obj.get_category_display()
    
        def get_authors(self, obj):
            """ 方法字段对应的方法 """
            authors_query_set = obj.author.all()
            return [{"id": author_obj.id, "name": author_obj.name} for author_obj in authors_query_set]
    
        def get_publisher_info(self, obj):
            """ 方法字段对应的方法 """
            publisher_obj = obj.publisher
            return {"id": publisher_obj.id, "title": publisher_obj.title}
    
        class Meta:
            """ 初始化 """
            model = Book  # 绑定的表
            # fields = ["id", "title", "pub_time"]  # 自定义字段
            fields = "__all__"  # 取所有字段
            # depth = 1  # 嵌套关系找1层
            # {"write_only": True}:GET请求不展示这些字段
            extra_kwargs = {"category": {"write_only": True},
                            "publisher": {"write_only": True},
                            "author": {"write_only": True}}
    
    
返回