zoukankan      html  css  js  c++  java
  • rest_framework序列化,反序列化

    序列化组件

    from rest_framework.response import Response
    1.Response本质也是继承了httpresponse,比httpResponse还强大,传入一个字典,列表可以序列化
    2.会根据不同的请求客户端,返回不同的东西,如果是浏览器访问的话就返回一个页面,如果是手机端的话就返回数据
    from django.db import models
    
    # Create your models here.
    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        publish_date = models.DateField()
    
        publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE)
        authors=models.ManyToManyField(to='Author')
        def __str__(self):
            return self.name
    
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        age = models.IntegerField()
    
    
    
    
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=32)
        email = models.EmailField()
    models.py
    #在settings里面INSTALLED_APPS里面加入"rest_framework"
    -序列化组件
    -使用drf的序列化组件
    from rest_framework.response import Response #(drf返回数据的时候使用)
    新建一个文件夹app01下的serializer.py
    -在视图中使用序列化的类
    -1 实例化序列化的类产生对象,在产生对象的时候,传入需要序列化的对象(queryset)
    -2 对象.data
    -3 return Response(对象.data)

    -高级用法:
    -source:可以指定字段(name publish.name),可以指定方法,
    -SerializerMethodField搭配方法使用(get_字段名字)
    publish_detail=serializers.SerializerMethodField(read_only=True)
    def get_publish_detail(self,obj):
    return {'name':obj.publish.name,'city':obj.publish.city}
    -read_only:反序列化时,不传
    -write_only:序列化时,不显示

    序列化的两种方式

      -序列化的两种方式
    -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对象


    views.py
    from django.shortcuts import render,HttpResponse
    
    # Create your views here.
    from rest_framework.views import APIView
    from app01 import models
    from rest_framework.serializers import Serializer
    
    
    from rest_framework.response import  Response
    from django.core import serializers
    # 把对象转换成json格式字符串
    from app01.app01serializer import BookSerializer
    class Books(APIView):
        def get(self,request):
            response={'code':100,'msg':'查询成功'}
            books=models.Book.objects.all()
            #了解
            # ret = serializers.serialize("json", books)
            #如果序列化多条,many=True(也就是queryset对象,就需要写)
            #如果序列化一条(可以不写)就是一个book对象,instance是要序列化的对象
            bookser=BookSerializer(instance=books,many=True)
            # print(type(bookser.data))
            # bookser.data 是一个returnList的类型
            response['data']=bookser.data
            return Response(response) #response可以放returnlist也就是列表,也可以是字典,就是不能是对象
        #使用继承了Serializers序列化类的对象,反序列化
        # def post(self,request):
        #     #实例化产生一个序列化类的对象,data是要反序列化的字典
        #     # print(request.data)
        #     bookser=BookSerializer(data=request.data)
        #     if bookser.is_valid():
        #         #清洗通过的数据
        #         ret=bookser.create(bookser.validated_data)
        #
        #     return Response()
        #使用继承了ModelSerializers序列化类的对象,反序列化
        def post(self,request):
            #实例化产生一个序列化类的对象,data是要反序列化的字典
            bookser=BookSerializer(data=request.data)
            # bookser.data
            if bookser.is_valid(raise_exception=True):
                #清洗通过的数据
                bookser.save()
            else:
                print(bookser.errors['name'][0])
            return Response()

     app01serializer.py

    from
    app01 import models from rest_framework import serializers class AuthorSerializer(serializers.Serializer): name=serializers.CharField() age=serializers.CharField() # class BookSerializer(serializers.Serializer): # #指定source='name' ,表示序列化模型表中的name字段,重名命为name5(name和source='name'指定的name不能重名) # name5=serializers.CharField(source='name') # #write_only 序列化的时候,该字段不显示 # #read_only 反序列化的时候,该字段不传 # price=serializers.CharField(write_only=True) # #如果要取 出版社的city source='publish.city' publish=serializers.CharField(source='publish.name') # #source不但可以指定一个字段,还可以指定一个方法 # book_type = serializers.CharField(source='get_xx_display',read_only=True) # #序列化出版社的详情,指定SerializerMethodField之后,可以对应一个方法,返回什么内容,publish_detail就是什么内容 publish_detail=serializers.SerializerMethodField(read_only=True) # #对应的方法固定写法get_字段名 # def get_publish_detail(self,obj): # # print(type(obj)) # return {'name':obj.publish.name,'city':obj.publish.city} # # #返回所有作者信息 authors=serializers.SerializerMethodField(read_only=True) # def get_authors(self,obj): # # return [ {'name':author.name,'age':author.age} for author in obj.authors.all()] # authorser=AuthorSerializer(obj.authors.all(),many=True) # return authorser.data # # def create(self, validated_data): # ret=models.Book.objects.create(**validated_data) # return ret from rest_framework import exceptions from app01 import models class BookSerializer(serializers.ModelSerializer): class Meta: model=models.Book # fields=('nid','name') #不能跟fields同时使用 # exclude=['name',] fields=('__all__') #深度是1,官方建议不要超过10,个人建议不要超过3 # depth=1 # xx=serializers.CharField(source='get_xx_display') # authors=serializers.SerializerMethodField() # def get_authors(self,obj): # ret=AuthorSerializer(instance=obj.authors.all(),many=True) # return ret.data # name=serializers.CharField() #反序列化的校验(局部校验,全局校验) def validate_name(self,value): print(value) raise exceptions.ValidationError('不能以sb开头') # if value.startswith('sb'): # raise ValidationError('不能以sb开头') # return value def validate(self,attrs): print(attrs) # if attrs.get('price')!=attrs.get('xx'): # raise exceptions.ValidationError('name和price相等,不正常') return attrs

    models.py

    from django.db import models
    
    # Create your models here.
    class Book(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        publish_date = models.DateField(null=True)
        xx=models.IntegerField(choices=((0,'文学类'),(1,'情感类')),default=1,null=True)
        publish = models.ForeignKey(to='Publish',to_field='nid',on_delete=models.CASCADE,null=True)
        authors=models.ManyToManyField(to='Author')
        def __str__(self):
            return self.name
        def test(self):
            return 'xxx'
    
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        age = models.IntegerField()
    
    
    
    class Publish(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=32)
        email = models.EmailField()
    
        def __str__(self):
            return self.name


    总结:
       -django原生的序列化(了解)
    -drf序列化:基本使用
    -定义一个类BookSer,继承Serializers
    -在类写字段
    -name=serializer.CharField()

    -在视图中使用:
    -book_ser=BookSer(instance=要序列化的对象,many=True)
    -序列化之后的数据book_ser.data
    -drf序列化类的两种写法
    -继承Serializer
    -每一个字段都需要自己写,跟表模型有对应关系,source:指定的是表模型中哪个字段(可以指定字段,可以指定方法)
    -SerializerMethodField 跟它绑定一个方法(get_字段名),方法返回什么,该字段就是什么
    -继承ModelSerializer
    -重写字段
    class Meta:
    model=表模型
    fields='__all__'
    fields=(字段一,字段二)
    exclude=(排除的字段)
    depth=1 :尽量少用
    -反序列化
    -继承Serializer
    -重写create方法,自己写保存逻辑

    -继承ModelSerializer
    -不管是新增还是修改,都调用save方法
    -校验:
    -局部:validate_字段名(self,value):
    -全局:validate(self,attrs)
    -源码分析
    -数据校验部分源码
    -序列化类实例化产生对象时走的逻辑
    -many控制生成的对象是什么
    -序列化的时候,走的逻辑
    
    
    
     
  • 相关阅读:
    Ajax与JSON的一些总结
    ASP.NET Cache的一些总结
    8个非常有用的HTML5工具
    Trie树和Ternary Search树的学习总结
    仿微博字符统计和本地存储功能的实现
    SQL Server 高性能写入的一些总结
    Deadlock的一些总结
    Javascript Context和Scope的一些学习总结
    网络攻击技术——Broken authentication
    Ember.js的一些学习总结
  • 原文地址:https://www.cnblogs.com/huangxuanya/p/11143394.html
Copyright © 2011-2022 走看看