• restframework——序列化组件


    models.py

    from django.db import models
    
    # Create your models here.
    __all__ = ["Book", "Publisher", "Author"]
    
    
    class Book(models.Model):
        title = models.CharField(max_length=32)
        CHOICES = ((1, "Python"), (2, "Linux"), (3, "go"))
        category = models.IntegerField(choices=CHOICES, null=True, blank=True)
        pub_time = models.DateField()
        publisher = models.ForeignKey(to="Publisher")
        authors = models.ManyToManyField(to="Author")
    
    
    class Publisher(models.Model):
        title = models.CharField(max_length=32)
    
        def __str__(self):
            return self.title
    
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
    
        def __str__(self):
            return self.name

      urls.py

    from django.conf.urls import url, include
    from .views import BookView,BookEditView
    
    urlpatterns = [
        url(r'^book/$', BookView.as_view()),
        url(r'^book/(?P<id>d+)', BookEditView.as_view()),
    
    ]

    序列化 post请求(新增数据)

     视图函数

    from rest_framework.response import Response
    from djangoDemo.models import Book
    from .serializers import BookSerializer
    
    class BookView(APIView):
        def get(self, request):
            book_queryset = Book.objects.all()
            # [book_obj, ]
            # 用序列化器进行序列化
            ser_obj = BookSerializer(book_queryset, many=True)
            return Response(ser_obj.data)
    
        # 新增数据
        def post(self, request):
            # 从前端得到的请求数据
            book_obj = request.data
            # print(book_obj)
            # BookSerializer(data=book_obj) 反序列化的时候必须指定data=
            ser_obj = BookSerializer(data=book_obj)
            # 对数据进行校验
            if ser_obj.is_valid():
                ser_obj.save()
                print(ser_obj.validated_data)
                return Response(ser_obj.validated_data)
            return Response(ser_obj.errors)

     序列化器: serializers.py

    一.声明序列化类

    from rest_framework import serializers
    from djangoDemo.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)

    二.外键关系的序列化

    class BookSerializer(serializers.Serializer):
        id = serializers.IntegerField(required=False)
        title = serializers.CharField(max_length=32, validators=[my_validate,])
        pub_time = serializers.DateField()
        category = serializers.CharField(source="get_category_display", read_only=True)
        post_category = serializers.IntegerField(write_only=True)
    
        publisher = PublisherSerializer(read_only=True)
        # 内部通过外键关系的id找到了publisher_obj
        # PublisherSerializer(publisher_obj)
        authors = AuthorSerializer(many=True, read_only=True)

    反序列化

    当前端给我们发post的请求的时候~前端给我们传过来的数据~我们要进行一些校验然后保存到数据库~

    这些校验以及保存工作,DRF的Serializer也给我们提供了一些方法了~~

    首先~我们要写反序列化用的一些字段~有些字段要跟序列化区分开~~

    Serializer提供了.is_valid()  和.save()方法~~

    -- 正序和反序列化字段不统一
    -- required=False 只序列化不走校验
    -- read_only=True  只序列化用
    -- write_only=True  只反序列化用
    -- 重写create方法

    -- 验证通过返回ser_obj.validated_data

    -- 验证不通过返回ser_obj.errors
    class BookSerializer(serializers.Serializer):
        # required=False 表示不做校验
        id = serializers.IntegerField(required=False)
        title = serializers.CharField(max_length=32,validators=[my_validate,])
        pub_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):
            # print(validated_data)
            # 这是validated_data
            '''
             {
            'title': '侠客行', 'pub_time': datetime.date(2018, 11, 14), 'post_category': 1, 'publisher_id': 1, 'author_list': [1, 2]
            }
            '''
            book_obj = Book.objects.create(title=validated_data['title'], pub_time=validated_data['pub_time'],
                                           category=validated_data['post_category'],
                                           publisher_id=validated_data['publisher_id'])
            # 多对多字段添加
            book_obj.authors.add(*validated_data['author_list'])
            return book_obj
    View Code

    反序列化put/patch请求(更新数据)

    视图函数 views.py

    class BookEditView(APIView):
        def get(self, request, id):
            book_obj = Book.objects.filter(id=id).first()
            ser_obj = BookSerializer(book_obj)
            return Response(ser_obj.data)
        # put post 都是反序
        # 更新数据
        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()
                return Response(ser_obj.validated_data)
            return Response(ser_obj.errors)

    序列化器 serializers.py

    -- 重写update方法
    -- ser_obj = BookSerializer(instance=obj, data=request.data, partial=True)
    -- 验证通过返回ser_obj.validated_data
    -- 验证不通过返回ser_obj.errors 
        def update(self, instance, validated_data):
            instance.title = validated_data.get('title', instance.title)
            instance.pub_time = validated_data.get('pub_time', instance.pub_time)
            instance.category = validated_data.get('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

    验证

    单个字段的验证  权重 222
        def validate_title(self, value):
            print(2222)
            # value就是title的值 对value处理
            if "python" not in value.lower():
                raise serializers.ValidationError("标题必须含有python")
    
    多个字段的验证  权重 333
        def validate(self, attrs):
            print(33333)
            # attrs 字典有你传过来的所有的字段  >>>>OrderedDict([('title', 'python'), ('post_category', 2)])
            print(attrs)
            if "python" in attrs["title"].lower() or attrs["post_category"] == 1:
                return attrs
            else:
                raise serializers.ValidationError("分类或标题不合符要求")
    
    自定义的验证  权重 111
    def my_validate(value):
        print(111, value)
        if '敏感信息' in value.lower():
            raise serializers.ValidationError('有敏感词汇')
        return value
    
            配置:  给字段加validators=[my_validate]
                title = serializers.CharField(max_length=32,validators=[my_validate,]) 
           

    ModelSerializer

    现在我们已经清楚了Serializer的用法,会发现我们所有的序列化跟我们的模型都紧密相关~

    那么,DRF也给我们提供了跟模型紧密相关的序列化器~~ModelSerializer~~

      -- 它会根据模型自动生成一组字段

      -- 它简单的默认实现了.update()以及.create()方法

    一.定义一个ModelSerializer序列化器

    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = Book
            fields = "__all__"
            # fields = ["id", "title", "pub_time"]
            # exclude = ["user"]
            # 分别是所有字段 包含某些字段 排除某些字段

    外键关系的序列化

    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = Book
            fields = "__all__"
            # fields = ["id", "title", "pub_time"]
            # exclude = ["user"]
            # 分别是所有字段 包含某些字段 排除某些字段
            depth = 1
    # depth 代表找嵌套关系的第几层
    
    外键关系序列化

    方法字段-- SerializerMethodField() 

    def get_字段名称(self, obj):
        obj  每次序列化的模型对象
        return 自定义的数据
    class BookSerializer(serializers.ModelSerializer):
        # category_display = serializers.SerializerMethodField(read_only=True)
        # # publisher_info = serializers.SerializerMethodField(read_only=True)
        # # authors_info = serializers.SerializerMethodField(read_only=True)
        # def get_category_display(self,obj):
        #     return obj.get_category_display()
        publisher_info = serializers.SerializerMethodField(read_only=True)
        category_info = serializers.SerializerMethodField(read_only=True)
        authors_info = serializers.SerializerMethodField(read_only=True)
    
        # category = serializers.SerializerMethodField()
    
        def get_publisher_info(self, obj):
            print(111, obj)
            publisher_obj = obj.publisher
            return {'id': publisher_obj.id, 'title': publisher_obj.title}
    
        def get_category_info(self, obj):
            return obj.get_category_display()
    
        def get_authors_info(self, obj):
            authors_querset = obj.authors.all()
            return [{"id": author.id, "name": author.name} for author in authors_querset]

    Meta中其它关键字参数

    class BookSerializer(serializers.ModelSerializer):
        chapter = serializers.CharField(source="get_chapter_display", read_only=True)
    
        class Meta:
            model = Book
            fields = "__all__"
            # fields = ["id", "title", "pub_time"]
            # exclude = ["user"]
            # 分别是所有字段 包含某些字段 排除某些字段
            depth = 1
            read_only_fields = ["id"]
            extra_kwargs = {"title": {"validators": [my_validate,]}}
    
    Meta中参数
  • 相关阅读:
    哈夫曼编码拓展题
    TrieTree
    并查集
    hash一致性
    布隆过滤器
    如何计算完全二叉树的结点数?
    如何翻转单链表和双向链表
    如何判断是搜索二叉树与完全二叉树
    文本分类之特征描述vsm和bow
    文本分类概述
  • 原文地址:https://www.cnblogs.com/shuai1993/p/9966357.html
Copyright © 2020-2023  润新知