zoukankan      html  css  js  c++  java
  • serializer组件

     

    rest_framework序列化之Serialzier

    ***记得先在apps里面注册rest_framework***

    models.py

    class Book(models.Model):
        name = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=8, decimal_places=2)
        publish_time = models.DateField()
        category = models.IntegerField(choices=((1, "文学类"), (2, "艺术类"), (3, "其他类")), null=True)
        authors = models.ManyToManyField(to="Author")
        publish = models.ForeignKey(to="Publish", null=True)
    
    
    class Publish(models.Model):
        name = models.CharField(max_length=32)
        addr = models.CharField(max_length=32)
        email = models.EmailField()
    
        def __str__(self):
            return self.name
    
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
    View Code

    urls.py

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^books/(?P<id>d*)/', views.BookDetail.as_view()),
        url(r'^books/$', views.Book.as_view()),
        url(r'^authors/$', views.Author.as_view()),
    ]
    

    app02serializer.py

    class BookSerializer(serializersSerializer):
        name = serializers.CharField()
        price = serializers.CharField()
        publish_time = serializers.DateField()
        category = serializers.SerializerMethodField()
      # source可以指定摸一个具体字段(),也可以指定为一个方法
      # publish = serializers.CahrField(source="publish.name")
        # category = serializers.CharField(source="get_category_display")
      # 使用SerializerMethodField,后面必须跟一个方法(get_字段名)
        publish = serializers.SerializerMethodField()
        authors = serializers.SerializerMethodField()
    
    
        def get_category(self, obj):
            return obj.get_category_display()
    
    
        def get_publish(self, obj):
            return PublishSerializer(obj.publish).data
        
        
        def get_authors(self, obj):
            res = AuthorSerializer(obj.authors.all(), many=True)
            return res.data
        
        # 使用Serializer序列化,添加数据时需重写create方法
        def create(self, validated_data):
            authors = validated_data.pop('authors')
            obj = models.Book.objects.create(**validated_data)
            obj.authors.add(*authors)
            return obj
    View Code

    views.py

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from app02 import models
    from app02 import app02serializer
        
        def post(self, request):
            back_dic = {"code": 100, "msg": "新增成功"}
            book_servializer = app02serializer.BookSerializer(data=request.data)
            if book_servializer.is_valid():
                print(book_servializer.validated_data)
                # 序列化使用Serializer时,添加数据需要使用重写的create方法
                book_servializer.create(book_servializer.validated_data)
                return Response(back_dic)
    

      

    rest_framework序列化之ModelSerialzier

    app02serializer.py

    from app02 import models
    from rest_framework import serializers
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = ("__all__")
            # fields=['id','name','authors','publish']
            # exclude=["name", ]   # 与fields不能同时使用
            # depth = 1  # 深度控制
    
    class PublishSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Publish
            fields = "__all__"
    
    class AuthorSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.Author
            fields = "__all__"

    views.py

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from app02 import models
    from app02 import app02serializer
    
    # 由于每个视图类中都会有get方法,因此可抽取出放到一个基类中,其他方法一样
    class Get(object):
        def get(self, request, *args, **kwargs):
            response = {"code": 100, "msg": "查看成功"}
            book_list = self.cls.objects.all()
            # 序列化多个对象需传入参数many
            data = self.ser(instance=book_list, many=True).data
            response["data"] = data
            return Response(response)
    
    
    class Book(APIView, Get):
        cls = models.Book
        ser = app02serializer.BookSerializer
    
        def post(self, request, *args, **kwargs):
            response = {"code": 100, "msg": "新增成功"}
            book_serializer = app02serializer.BookSerializer(data=request.data)
            if book_serializer.is_valid():
                book_serializer.save()
            else:
                response["code"] = 101
                response["msg"] = book_serializer.errors
            return Response(response)
    
    
    class BookDetail(APIView):
        def get(self, request, id, *args, **kwargs):
            response = {"code": 100, "msg": "查看成功"}
            book_obj = models.Book.objects.filter(pk=id).first()
            book_serializer = app02serializer.BookSerializer(instance=book_obj)
            response["data"] = book_serializer.data
            return Response(response)
    
        def put(self, request, id, *args, **kwargs):
            response = {"code": 100, "msg": "修改成功"}
            book_obj = models.Book.objects.filter(pk=id).first()
            # 更新数据需传入对象本身以及数据(包括未更新的数据)
            book_serializer = app02serializer.BookSerializer(instance=book_obj, data=request.data)
            if book_serializer.is_valid():
                book_serializer.save()
            else:
                response["code"] = 102
                response["msg"] = book_serializer.errors
            return Response(response)
    
        def delete(self, request, id, *args, **kwargs):
            response = {"code": 100, "msg": "删除成功"}
            models.Book.objects.filter(pk=id).delete()
            return Response(response)
    
    
    class Author(APIView, Get):
        cls = models.Author
        ser = app02serializer.AuthorSerializer
    View Code

     钩子函数

        # 局部钩子
        def validate_title(self, value):
            from rest_framework import exceptions
            raise exceptions.ValidationError('看你不顺眼')
            return value
    
        # 全局
        def validate(self, attrs):
            from rest_framework import exceptions
            if attrs.get('password') == attrs.get('confirm_password'):
                return attrs
            else:
                raise exceptions.ValidationError('不想等啊')

    序列化组件源码分析

    校验源码部分

    调用了 序列化对象.is_valid方法才走校验  ---->  内部走了self.run_validation方法(找该方法一定要从根上找) --->   Serializer类中找到了run_validation方法   

    --->    重点的地方:self.to_internal_value(局部钩子)/self.validate(全局钩子)  --->
    Serializer类中找到了to_internal_value,去对象内部反射validate_字段名的方法,如果不为None,直接执行,于是就执行了咱们自己写的局部校验的函数

    序列化类实例化many参数相关

    many=True的时候,生成的是列表中放了一个个的序列号化对象
    many=False 的时候,生成的是一个序列化对象

    序列化对象.data相关

    执行Serializer内的data方法--->又执行了父类(BaseSerializer)的data方法--->执行self.to_representation(其实执行的是Serializer内的to_representation方法)
    最终执行的是每个字段对象的get_attribute方法--->找字段对象的该方法-->在Field中找到了该方法
    --->执行了get_attribute(instance, self.source_attrs)--->self.source_attrs:每个字段source后面指定的根据.切分后的列表(publish.name:就会被分成[publish,name])
    如果是方法会执行方法,如果是字段,通过反射取出值

    
    
  • 相关阅读:
    selenium修改cookie
    unittest同时支持参数化和生成html报告
    webdriver API
    selenium中CSS选择器定位
    VirtualBox中安装CentOS 7_Linux
    Selenium常见问题
    RFS常见问题
    RFS--RequestLibrary
    Fiddler抓取HTTPS请求配置
    Redis
  • 原文地址:https://www.cnblogs.com/penghengshan/p/11129466.html
Copyright © 2011-2022 走看看