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])
如果是方法会执行方法,如果是字段,通过反射取出值

 


posted @ 2019-07-03 22:18  hengshan  阅读(362)  评论(0编辑  收藏  举报