• 序列化


    #序列化组件是干什么的,
    #数据需要处理,不可能把queryset对象传给前台

    一、自己用for循环处理(太麻烦)

    class Books(APIView):
        def get(self,request,*args,**kwargs):
            response = {'status': 100, 'data': None}   
            ret=models.Book.objects.all()
            print(ret)
    #<QuerySet [<Book: 西游记>, <Book: 红楼梦>, <Book: 三国演义>, <Book: 水浒传>]>
            l1=[{'name':book.name} for book in ret]
            l2=[{'name':book.name,'price':book.price} for book in ret]        #展示的字段可控
            print(l1)
            print(l2)      
    #[{'name': '西游记'}, {'name': '红楼梦'}, {'name': '三国演义'}, {'name': '水浒传'}]
    
    
    #[{'name': '西游记', 'price': Decimal('11.00')}, {'name': '红楼梦', 'price': Decimal('22.00')}, {'name': '三国演义', 'price': Decimal('23.00')}, {'name': '水浒传', 'price': Decimal('3.00')}]
    
            response['data'] = l1
            return JsonResponse(response,  json_dumps_params={'ensure_ascii': False})

    二、用django提供的序列化组件

    # django提供的序列化组件(不可控,展示所有字段,有时候我们并不需要)
    #导入   from django.core import serializers
            ret=serializers.serialize('json','queryset对象')
            ret就是序列化之后的字符串了,不需要再序列化了
    
    from django.core import serializers
    class Books(APIView):
        def get(self,request):
            response = {'status': 100, 'data': None}
            books = models.Book.objects.all()
    
            # 先构造出所有书籍的字典的列表
            # 用django提供的序列化组件
            ret=serializers.serialize('json',books)
            print(ret)
    
            # 返回数据是json格式数据
            response['data'] = ret
            return HttpResponse(ret)

    三、rest-framework序列化之Serializer

    from django.db import models
    
    # Create your models here.
    
    
    class Book(models.Model):
        title=models.CharField(max_length=32)
        price=models.IntegerField()
        pub_date=models.DateField()
        publish=models.ForeignKey("Publish")
        authors=models.ManyToManyField("Author")
        def __str__(self):
            return self.title
    
    class Publish(models.Model):
        name=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()
        def __str__(self):
            return self.name
    models部分

    mySer.py

    #可以在views.py中直接写,也可创建一个py文件,在里边写
    mySer.py
    #1 先导入from rest_framework import serializers
    
    #2 写一个类,继承serializers.Serrializer  
    class BookSerializer(serializers.Serializer):     #在类内部写想要的字段
        name = serializers.CharField()
        xx = serializers.CharField(source='name')   #同上,就把字段名改为xx           
        price= serializers.CharField()              
        publish = serializers.CharField()         #支持跨表查询      
        test = serializers.CharField(source='publish.test')   #指定函数
    
    
    另外,source不仅可以指定字段,也可以指定方法(函数),拿到的是函数的返回结果,没有return,则拿到None
    -------------------------------------------------------------------
    class BookSerializer(serializers.Serializer):
    
         publish=serializers.SerializerMethodField()
        # 方法名:叫get_字段名,要传参数,参数是:当前book对象
        def get_publish(self,obj):
            # obj 是当前book对象
            dic={'name':obj.name,'email':obj.publish.email}
            return dic

    views.py

    # 使用:
    
    from app01 import models
    from rest_framework.views import APIView
    from app01.mySer import BookSerializer
    from django.http import JsonResponse
    
    
    class Book(APIView):
        def get(self,request,*args,**kwargs):
            ret = models.Book.objects.all()   #拿到所有queryset对象
    
            book_serializer = BookSerializer(instance=ret,many=True)   #需要的两个参数
    
            return JsonResponse(book_serializer.data,safe=False)
    
    #先生成对象,需要传参数 instance:要序列化的对象   (可能是queryset,也可能是单个对象)    
    #序列化多条  many=True
    
    #instance可不写,按位置传参
    View Code

    上边的是一对多字段,多对多字段

    class BookSerializer(serializers.Serializer):
       publish=serializers.SerializerMethodField()
        def get_publish(self,obj):
            dic={'name':obj.publish.name,"city":obj.publish.city}
            return dic
    #方式一
        authors = serializers.SerializerMethodField()
        def get_authors(self,obj):
            aus=obj.authors.all()
            li=[]
            for a in aus:        #通过for循环拿到所有作者
                c=li.append({'name':a.name,'age':a.age})
                return c
    #方式二
        authors = serializers.SerializerMethodField()
        def get_authors(self,obj):
            aus = obj.authors.all()      #拿到书的所有作者
            aus_author = AuthorSerializer(aus,many=True)
            return aus_author.data
    SerializerMethodField

    四、rest-framework序列化之ModelSerializer

    #上边的都需要手动写字段
    
    class BookSerializers(serializers.ModelSerializer):
    
        class Meta:       #必须写这么一个类
            model = models.Book     #指定模型表
            # fields = "__all__"         #展示所有字段
            fields=['nid','title','authors','publish']      #展示指定字段

    # exclude=('nid',) # 哪个字段不展示 # depth = 1 #深度控制,写 几 往里拿几层,层数越多,响应越慢, #重写属性(如果没有指定deoth,内层的仅显示id,也就是跨表的字段没有显示出来,仅显示当前表,) publish=serializers.SerializerMethodField() def get_publish(self,obj): return obj.publish.name authors=serializers.SerializerMethodField() def get_authors(self,obj): ret=obj.authors.all() ss=AuthorSerializer(ret,many=True) return ss.data

    五、生成hypermedialink(快速生成链接)

    #关键是怎么拼接"http://127.0.0.1:8000/publish/1"这个域名

    views.py

    from app01.mySer import BookSerializer
    from django.http import JsonResponse,HttpResponse
    from app01 import models
    
    from rest_framework.views import APIView
    class Books(APIView):
        def get(self,request,*args,**kwargs):
            ret = models.Book.objects.all()
            book_ser = BookSerializer(ret, many=True, context={'request': request})
              # context={'request': request},可以从request中拿到http://127.0.0.1:8000
         
            return JsonResponse(book_ser.data,safe=False)
    
    class Publish(APIView):
        def get(self,request,*args,**kwargs):
            return HttpResponse('ok')

    urls.py

    url(r'^publish/(?P<pk>d+)',views.Books.as_view(),name='pub_link_name'),
    #name='pub_link_name,取别名,方便反向解析

    mySer.py

    from rest_framework import serializers
    
    class BookSerializer(serializers.Serializer):
        name = serializers.CharField()
        # publish = serializers.CharField()
        publish = serializers.HyperlinkedIdentityField(view_name='pub_link_name',lookup_field='publish_id',lookup_url_kwarg='pk')
    
    
    #view_name='pub_link_name',就是urls中的name,这里拿到publish
    
    #lookup_field:根据表的哪个字段,来拼路径
    
    #,lookup_url_kwarg='pk',反向解析有名分组的名字

    六、请求数据校验与保存

    class BookSerializers(serializers.ModelSerializer):
        class Meta:
            model=Book
            fields="__all__"
    
    #————————
    class BookView(APIView):
    
        def post(self, request):
            books=BookSerializers(data=request.data)     #books是BookSerializers的对象
            if books.is_valid(): #是否校验通过
                bs.save()      #把数据同步到数据库 
                                # BookSerializers中没有save方法,找父类,ModelSerializer有,
    如果BookSerializers继承的是serializers.Serializer,该类中没有save方法,所以只有继承了ModelSerializer才能掉用save方法
                return Response(bs.data)
            else:
    
                return Response(bs.errors)                
    新增
    # 前提:
    # 1)序列化类中不能修改原字段的深度
    # 2)通过 data=请求数据包 得到可以操作orm的序列化对象,instance来明确修改的对象,校验成功后还是走save()来更新
    # 3)必须先校验,才能保存或更新
    
    #
    class Books(APIView):
        """
        {
            "name":"水浒传",
            "price":"88.88",
            "author":[1, 2, 3 ]
        }
        """
        def post(self, request):
            book_dic = request.data
            book_json = objson.BookJson(data=book_dic)
               # 数据的校验
            if book_json.is_valid():
                book_json.save()  # 不涉及跨表操作
            return Response({
                'status': 0,
                'msg': 'ok',
                'results': book_json.data
            })
    # 查改删
    class Book(APIView):
        def get(self, request, id):
            book_obj = models.Book.objects.filter(pk=id).first()
            book_data = objson.BookJson(book_obj).data
            return Response({
                'status': 0,
                'msg': 'ok',
                'results': book_data
            })
        def put(self, request, id):
            book_obj = models.Book.objects.filter(pk=id).first()
            # instance来明确修改的对象,校验成功后还是走save()来保存
            book_json = objson.BookJson(data=request.data, instance=book_obj)
            if book_json.is_valid():
                book_json.save()
            return Response({
                'status': 0,
                'msg': 'ok',
                'results': book_json.data
            })
        def delete(self, request, id):
            models.Book.objects.filter(pk=id).delete()
            return Response({
                'status': 2,
                'msg': 'delete success',
            })
    增删改
    # views.py
    class Books(APIView):
        def post(self, request):
            book_dic = request.data
            book_json = objson.BookJson(data=book_dic)
               # 数据的校验
            if book_json.is_valid():
                # book_json.save()  # 不涉及跨表操作
                return Response({
                    'status': 0,
                    'msg': 'ok',
                    'results': book_json.data
                })
            return Response({
                'status': 0,
                'msg': book_json.errors,
            })
    
        
    # objson.py
    class BookJson(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = '__all__'
    
        # 认证
        name = serializers.CharField(
            max_length=5,
            min_length=1,
            error_messages={
                "max_length": "太长了",
                "min_length": "太短了",
            }
        )
    
        # 局部钩子
        def validate_name(self, value):
            from rest_framework.exceptions import ValidationError
            if 'sb' in value:
                raise ValidationError("出现了敏感词汇")
            return value
    
    
        # def validate_price(self, value):
        #     from rest_framework.exceptions import ValidationError
        #     if float(value) < 0:
        #         raise ValidationError("价格不合理")
        #     return
        
        
        
    # 了解:如果多个字段直接协同校验,采用全局钩子
    def validate(self, attrs):
        from rest_framework.exceptions import ValidationError
        pwd = attrs.get('pwd')
        re_pwd = attrs.get('re_pwd')
        if pwd == re_pwd:
            return attrs
        else:
            raise ValidationError('密码校验失败')
    数据校验
  • 相关阅读:
    jQuery之Ajax应用
    ELK安装配置简单使用
    saltstack其他运行模式
    saltstack syndic安装配置使用
    salt api
    saltstack api安装使用
    saltstack master minion安装配置简单使用
    zabbix api
    zabbix snmp、jmx配置使用
    phoenix安装
  • 原文地址:https://www.cnblogs.com/pdun/p/10879306.html
Copyright © 2020-2023  润新知