rest_framework序列化组件

rest_framework序列化组件

rest_framework序列化组件是干啥的?

rest_framework序列化组件就是将需要其他数据类型都转成字符串

项目有前后端分离和前后端不分离的,前后端不分离的项目可以通过模板语法直接将后端的变量,对象传给前端,前端可以直接使用,而前后端分离的项目就是后端只写逻辑不管前端,只需要提供接口就行了,并且整个后端不同的模块可以由不同的语言编写,那么他们怎么和前端交互呢?那就是字符串,字符串是所有语言通用的一个数据类型。


如何使用drf的序列化组件

1,先建表,完成表的迁移

执行 python manage.py makemigrations 和 python manage.py migrate

class Books(models.Model):
    name = models.CharField(max_length=32)
    author = models.CharField(max_length=32)
    xxx = models.CharField(max_length=32)
    ooo = models.CharField(max_length=32)
    publish = models.ForeignKey('Publish',null=True)
    def add(self):
        return self.name +':'+ self.author
class Publish(models.Model):
    name=models.CharField(max_length=32)
    email=models.EmailField()
    # def __str__(self):
    #     return self.name

 

2,新建一个序列化类,

序列化类有两种,一种继承serializers,一种继承ModelSerializer

from app01 import models
from rest_framework import serializers

class
Publish_ser(serializers.Serializer): name = serializers.CharField() email = serializers.EmailField() class BookSerializer(serializers.Serializer): id = serializers.CharField() title = serializers.CharField(source='name')#source='name'表示序列化表的name字段,title表示把name改成title来显示 author = serializers.CharField()#默认序列化author字段并且显示的也是author publish = serializers.CharField() xxx = serializers.CharField(source='add') publish_dic = serializers.SerializerMethodField() def get_publish_dic(self,obj):#obj就是当前的Books这个表对象 return {'name':obj.publish.name,'email':obj.publish.email

继承serializers的序列化类必须写需要序列化的字段,可以用source改显示的名字,

source:可以指定字段source='name'   可以跨表source=publish.name,也可以指定方法source='add'

read_only=True:反序列化时,不传,就是说这个字段不需要前端传过来,后端自己生成,比如用户创建的时间createtime
write_only=True:序列化时,不显示,write_only表示只能写,不能读。例如定义序列化器时,password字段(还有短信验证码等)通常指定write_only=True。在序列化时,即对象转为字典、JSON字符串时,字典、JSON字符不会包含这个字段。

就是说前端向后端取数据时不显示出来,比如我们登录的qq是找不到密码的显示的。

class BookModelerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Books #指定表模型
        fields = '__all__'
        # depth = 1
    publish = serializers.CharField(source='publish.name')
    publish_dic = serializers.SerializerMethodField()

    def get_publish_dic(self,obj):
        publish_list = models.Publish.objects.all()
        publish_ser = Publish_ser(instance=publish_list,many=True)
        return publish_ser.data
    name = serializers.CharField(max_length=5,min_length=2,error_messages={
        'max_length':'太长了',
        'min_length':'太短了',
    })
    def validate_name(self, value):
        from rest_framework import exceptions
        if value.startswith('sb'):
            raise exceptions.ValidationError('铭感词会')
        return value

继承ModelSerializer的序列化类需要指定表模型关键字model,还要指定需要序列化的字段,关键字fields,

fields = "__all__"表示将全部的字段都序列化,显示的就是每个字段具体的值,publish显示的是数字,要想显示publish表具体的数据有两种方法,

1):可配置depth=1,显示深度为1表示会显示出其深度为1的关联表,depth推荐最大不要超过3;

2):还可以使用SerializerMethodField,如上publish_dic字段,使用它后后面必须定义一个 get_"字段名"  的函数,这个函数的返回值就会当成publish_dic的值。

如果想重写字段,在class:Meta上面或者下面写:name=serialzier.CharField(source='字段,方法,对象.字段'),这样会把原来的name字段覆盖掉,也可以写全新的字段比如publish_dic

 

fields = ('name','author')表示只序列化name和author字段,

在此基础上我们如果想在添加一个字段,publish = serializers.CharField(source='publish.name'),那么就必须把publish加入到fields里面fields = ('name','author','publish')不然会报错

AssertionError: The field 'publish' was declared on serializer BookModelerializer, but has not been included in the 'fields' option.

AssertionError:字段'publish_dic'在序列化程序BookModelerializer上声明,但未包含在'fields'选项中。

 

exclude=('name')表示除了name字段,其他字段都序列化

 

3,在视图中使用序列化的类

            -1 实例化序列化的类产生对象,在产生对象的时候,传入需要序列化的对象(queryset)
            -2 对象.data
            -3 return Response(对象.data)

class Books(APIView):
    def get(self,request,*args,**kwargs):
        book_list = models.Books.objects.all()
        data = {'code': 333, 'msg': '请求成功',}
        # book_ser = mySer.BookSerializer(book_list,many=True)
        book_ser = mySer.BookModelerializer(book_list,many=True)
        data['books'] = book_ser.data
        return Response(data)#返回的字典比较美观,做了格式化
        # return HttpResponse(json.dumps(data,ensure_ascii=False))#返回的字典挤到一堆,不方便看
    def post(self,request,*args,**kwargs):
        print(request.data)
        response = {'code':333,'msg':'新增成功'}
        #提交的字典
        book = request.data
        #传统方法创建对象保存
        #新方法,通过序列化组件保存
        book_ser = mySer.BookModelerializer(data=book)
        if book_ser.is_valid():
            book_ser.save()
        else:
            response['msg'] = '新增失败'
            response['error'] = book_ser.errors
        response['data'] = book_ser.data
        return Response(response)

class Book(APIView):
    def get(self,request,id,*args,**kwargs):
        data = {'code': 200, 'msg': '请求成功',}
        book_list = models.Books.objects.filter(pk=id).first()
        if book_list:
            book_ser = mySer.BookSerializer(book_list,many=False)
            data['books'] = book_ser.data
        else:
            data['msg'] = '请求的资源不存在'
            data['code'] = '111'
        return Response(data)

book_ser = mySer.BookModelerializer(book_list,many=True)

many:如果要序列化的对象book_list是一个queryset对象那么就要用many=Ture,如果是单个对象,那就需要many=False

序列化的两种方式
        Serializers:没有指定表模型
            -source:指定要序列化哪个字段,可以是字段,可以是方法
            - SerializerMethodField的用法
                authors=serializers.SerializerMethodField()
                def get_authors(self,obj):
                     ret=AuthorSerializer(instance=obj.authors.all(),many=True)
                     return ret.data
            
        -ModelSerializers:指定了表模型
            class Meta:
                model=表模型
                #要显示的字段
                fields=('__all__')
                fields=('id','name')
                #要排除的字段
                exclude=('name')
                #深度控制
                depth=1
            -重写某个字段
                在Meta外部,重写某些字段,方式同Serializers

 

反序列化

使用继承了Serializers序列化类的对象,反序列化
            -在自己写的序列化类中重写create方法
            -重写create方法,实现序列化
                -在序列化类中:
                    def create(self, validated_data):
                        ret=models.Book.objects.create(**validated_data)
                        return ret
                -在视图中:
                    def post(self,request):
                        bookser=BookSerializer(data=request.data)
                        if bookser.is_valid():
                            ret=bookser.create(bookser.validated_data)
                        return Response()
            
使用继承了ModelSerializers序列化类的对象,反序列化
            -在视图中:
                def post(self,request):
                    bookser=BookSerializer(data=request.data)
                    if bookser.is_valid():
                        ret=bookser.save()
                    return Response()
            
    -反序列化的校验
        -validate_字段名(self,value):
            -如果校验失败,抛出ValidationError(抛出的异常信息需要去bookser.errors中取)
            -如果校验通过直接return value
        -validate(self,attrs)
            -attrs所有校验通过的数据,是个字典
            -如果校验失败,抛出ValidationError
            -如果校验通过直接return attrs
            
    -读一读源码
        -全局和局部钩子源码部分
        -在序列化的时候,传many=True和many=False,生成的对象并不是一个对象
        -bookser.data
            -之前执行过,直接返回
            -get_attribute(instance, self.source_attrs)
                -self.source_attrs 是source指定的通过 . 切分后的列表
                -instance 当前循环到的book对象

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


   

posted @ 2019-07-02 22:55  团子I不哭  阅读(343)  评论(0编辑  收藏  举报