zoukankan      html  css  js  c++  java
  • drf序列化组件

    后台返回json数据的方式

    一.自己写for循环来处理
    def get(self,request):
        book_list = Book.objects.all()
        dic = [{'id':book.pk,'name':book.name} for book in book_list]
        return JsonResponse(dic,safe=False,json_dumps_params={'ensure_ascii':False})
    #safe=False 可以处理列表
    #json_dumps_params = {'ensure_ascii':False} 将默认编码ascii取消,使前台可以显示中文
    
    #优点:可以自己处理字段
    #缺点:单表查询ok,多表查询会复杂,无法处理时间字段
    
    
    二,使用django提供的序列化组件
    from django.core import serializers
    ret = serializers.serialize('json',book_list)
    return Httpresponse(ret)
    #优点:操作简单
    #缺点:不可控,将所有字段序列化,无法选择字段
    
    
    三.使用drf提供的序列化组件
    1.drf是一个app,使用前需在settings.py文件中设置app配置中添加'rest_framework'
    2.导入
    from rest_framework import serializers
    from rest_framework.response import Response
    
    3.新建myserializer.py文件,创建类继承serializers.Serializer
    class BookSerializer(serializers.Serializer):
       
    4.在类内部写字段(需要被序列化的字段)
     name = serializers.CharField()
        desc = serializers.CharField()
        author = serializers.CharField()
    
    
    #source参数将name字段以xx显示返回给前台
    xx = serializers.CharField(source='name')
    #publish为外键,前台显示为对象,可以改写Publish类的__str__方法,将publish.name显示在前台,
    #也可以使用source参数将publish.name赋值给publish,source参数以需序列化类的对象为基础,即book.publish.name
    #可以通过book对象连表查询的数据都可以通过source返回给前台,
    publish = serializers.CharField(source = 'publish.name')
    #source也可以指定方法,源码以split('.')拆分成列表,for循环,是方法的话(callable)执行方法,此处将test方法的结果返回给test字段
    test = serializers.CharField(source='test')
    
    
    5.使用,先生成对象,需要传参数instance,instance可以是queryset对象,也可以是单个对象
    instance = 'queryset对象'时需设置参数many = True,源码会对列表进行序列化
    instance = '单个对象'时需设置参数many=False,源码会使用单个序列化
    
    from book.myserializers import BookSerializer
    from rest_framework.response import Response
    
    class Query(APIView):
        def get(self,request):
            book_list = Book.objects.all()
            book_ser = BookSerializer(instance=book_list,many=True)
            #使用drf提供的Response(继承了Httpresponse)返回数据,
            return Response(book_ser.data)
    
    6.返回字典book_ser.data #data为私有属性,实际是调用了data方法
    

    SerializerMethodField

    当返回的对象有多个时,比如一本书有多个作者
     author = serializers.CharField() 需要返回一个列表,此时需要用到SerializerMethodField()
    
    class BookSerializer(serializers.Serializer):
        name = serializers.CharField()
        desc = serializers.CharField()
        #1.定义字段
        author = serializers.SerializerMethodField()
        #2.定义对应方法,方法的返回值赋值给字段,以get_开头,才能被源码解析到
        def get_author(self,obj):
            author_list = obj.author.all()
            #这里使用了for循环
            #dic = [{'name':author.name,'phone':author.phone} for author in author_list]
            #return dic
            #也可以采用给author创建序列化类来实现
            author_ser=AuthorSerializer(instance=author_list,many=True)
            return author_ser.data
        
       
    class AuthorSerializer(serlizers.Serializer):
            name = serializers.CharField()
            phone = serializers.CharField()
    
    #优点:可控,可扩展
    
    

    ModelSerializer

    Serializer类并没有指明给哪个类进行序列化
    使用ModelSerializer可以指明给哪个类进行序列化
    
    from app01 import models
    #继承ModelSerializer
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            #指定表模型
            model = Book
            #指定要序列化的表字段
            fields = ['nid','name']
            #指定序列化所有字段
            #fields = '__all__'
            #指定不要序列化的表字段(不能跟fields连用)
            #exclude=['id']
            #深度,连表的深度,官方建议最多写10,个人建议3
            depth=1	
        #可以再自定义自己要序列化的字段
        publish = serializer.CharField(source='publish.name')
    
    from book.models import *
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = Book
            fields = ['name','desc','author']
            # depth = 1
        author = serializers.SerializerMethodField()
        #注意:自定义的字段必须在fields中定义,否则报错
        def get_author(self, obj):
            author_list = obj.author.all()
            author_ser = AuthorSerializer(instance=author_list, many=True)
            return author_ser.data
        # publish = serializers.CharField(source='publish.name')
    

    序列化单个对象

    class Book(APIView):
        def get(self,request,id,*args,**kwargs):
            book = models.Book.objects.filter(pk=id).first()
            #单个对象,many=False,instance必须是单个对象,而不是querset对象(都是列表)
            book_ser = BookSerializer(instance=book,many=False)
            return Response(book_ser.data)
    

    反序列化组件

    
    class Books(APIView):
        def get(self, request):
            book_list = models.Book.objects.all()
            book_ser = BookSerializer(instance=book_list, many=True)
            return Response(book_ser.data)
    
        def post(self, request):
            res = {"staus":100,"msg":"新增成功","data":[]}
    `
            book_ser = BookSerializer(data=request.data)
            if book_ser.is_valid():
                book_ser.save()
                res["data"] =book_ser.data
            else:
                res["msg"]="新增失败"
                res["data"] = book_ser.errors
            return Response(res)
            # 没有继承ModelSerializer无法使用save,因为不确定保存给哪个表
    

    局部钩子

    
    函数名称:validate_字段名
    触发条件:字段名校验通过了,才会触发局部钩子
    from book.models import *
    from rest_framework.exceptions import ValidationError
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = Book
            fields = ['name','desc','author']
            # depth = 1
        author = serializers.SerializerMethodField()
    
        def get_author(self, obj):
            author_list = obj.author.all()
            author_ser = AuthorSerializer(instance=author_list, many=True)
            return author_ser.data
        # publish = serializers.CharField(source='publish.name')
    
        def validate_name(self,value):
            print(0)
            if value.startswith('sb'):
                raise ValidationError('不能以sb开头')
            return value
    

    全局钩子

    函数名称:validate
    触发条件:局部钩子通过后才会触发
    
    from book.models import *
    from rest_framework.exceptions import ValidationError
    class BookSerializer(serializers.ModelSerializer):
        class Meta:
            model = Book
            fields = ['name','desc','author']
            # depth = 1
        author = serializers.SerializerMethodField()
    
        def get_author(self, obj):
            author_list = obj.author.all()
            author_ser = AuthorSerializer(instance=author_list, many=True)
            return author_ser.data
        # publish = serializers.CharField(source='publish.name')
    
        def validate_name(self,value):
            if value.startswith('sb'):
                raise ValidationError('不能以sb开头')
            return value
    
        def validate(self, attrs):
            publish =attrs.get('publish')
            if not publish:
                raise ValidationError('不能为空')
            return attrs
    

    更新对象put方法

     def put(self, request, id, *args, **kwargs):
            res = {"staus": 100, "msg": "更新成功", "data": []}
            book = models.Book.objects.filter(pk=id).first()
            #更新的时候,反序列化内加入instance参数,保存的时候不需要instance
            book_ser = BookSerializer(data=request.data,instance=book)
            #进行save操作前必须判断是否通过校验,执行.is_valid才会去校验字段
            if book_ser.is_valid():
                book_ser.save()
                res["data"]= {"name":book.name,'desc':book.desc}
            else:
                res["msg"] = "更新失败"
                res["data"] = book_ser.errors
            return Response(res)
    
  • 相关阅读:
    酒里放茶,醉,未遂。
    利用自定义事件实现不同窗体间的通讯 Delphi篇
    主题:CS0016: 未能写入输出文件“c:\WINDOWS\Microsoft.NET\***.dll”错误处理
    delphi點擊窗體最小化,關閉按鈕時的托盤圖標設置
    delphi制作程序啟動歡迎窗體
    那年 那雪
    DOL魔盘解决方案
    专家解密“艳照门”背后三大安全陷阱
    jQuery获取Select选择的Text和 Value(转)
    技术列传 guava cache
  • 原文地址:https://www.cnblogs.com/robert-zhou/p/10601063.html
Copyright © 2011-2022 走看看