• DRF框架之 serializers 序列化组件


    1. 什么是序列化,其实在python中我们就学了序列化工具json工具,就是吧信息存为类字典形式

    2. DRF框架自带序列化的工具: serializers 

    3. DRF框架 serializers 分为:第一种 Serializer   第二种 ModelSerializer

    第一种用法之 Serializer

    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
    
    
        def test(self):    #注意: 这里是给后面序列化组件的source指定方法用的
            return str(self.price)+self.name
    
    
    class Author(models.Model):
        nid = models.AutoField(primary_key=True)
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        author_detail = models.OneToOneField(to='AuthorDatail',to_field='nid',unique=True,on_delete=models.CASCADE)
    
    
    class AuthorDatail(models.Model):
        nid = models.AutoField(primary_key=True)
        telephone = models.BigIntegerField()
        birthday = models.DateField()
        addr = models.CharField(max_length=64)
    
    
    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
    models层先创建数据表
    from  rest_framework import serializers
    from app.models import Book,Author
    
    ####################这里是serializers 实例化方法一的实现
    #
    class Bookserializer(serializers.Serializer):
        # 这里是通过rest_framwork 来实例化对象中的内容,返回给前端的数据信息
        id = serializers.CharField()
        # source指定数据库中的名字,前面可以自定义名字来使用,给前端显示的是自定义名字 bookname 是自己自定义的名字
        bookname = serializers.CharField(source='name')
    
        price = serializers.CharField()
        # source还可以通过对象继续点其他属性, 可以跨表点其他的想要的属性(这个只是拿到publish的单个字段)
        publish_name = serializers.CharField(source='publish.name')
        #注意source 还可以调用models中 Book 表内的方法
        maxprice = serializers.CharField(source='test')
    
    #注意,source 可以名字自定义显示,可以跨表链接其他想要的属性,还可以调用book表中的自定义的方法
        # publish字段,返回出版社的所有信息,包括id,name,email。。。。
        #     #SerializerMethodField配合一个方法,方法的返回值会付给publish
        #SerializerMethodField 可以拿到跨表内的多个字段,你吧想要的都返还回去就行了(这里是拿到publish的多个字段信息)
        publish = serializers.SerializerMethodField()
        #这里这里的obj 是当前序列化的对象 这里的对象就是book!!!!
        def get_publish(self,obj):
            return {'id':obj.publish.pk, 'name': obj.publish.name,'city':obj.publish.city}
    
    ####################这里是serializers 实例化方法一的实现
    自己创建个py文件,写上序列化显示的内容

    第二种用法之ModelSerializer

    ###################这里是serializers实例化实现方法二 的实现,调用ModelSerializer
    class Bookserializer(serializers.ModelSerializer):
        #这里一个meta类去调用Book这个表
        class Meta:
            model = models.Book
            #fields  是然他显示所有的内容,渲染出去
            fields = "__all__"         # '__all__' 是渲染全部出去
    #         #fields = ['id', 'name']     # ['....'] 是渲染指定的
    #         # exclude=['name']            #是除了name 之外的全部都渲染出去,不能和fields同时出现
    #         #depth = 3                   #深度 ,官方建议最多写10,深度显示所有的表
    #
        #这里是可以自定义,自定义显示publish的名字,
        publish_name = serializers.CharField(source='publish.name')
        publish = serializers.SerializerMethodField()
        #也可以拿到publish的多个字段信息
        def get_publish(self,obj):
            return {'id':obj.publish.pk, 'name':obj.publish.name}
    
    ###################这里是serializers实例化实现方法二 的实现,调用ModelSerializer
    最后建议使用serializers.ModelSerializer 来实现序列化 ,因为在修改接口和添加接口 对save() 有很好的依赖关系
    第二种序列化的方法(建议这种)
    # 局部钩子函数,对单个字段校验
        #校验name字段不能以sb开头
        def validate_name(self,value):
            if value.startswith('sb'):
                #不能让你过
                raise ValidationError('书名不能以sb开头')
            else:
                return value
    
        #全局钩子函数,对全局字段进行校验
        # def validate(self,a):
        #     # print(a)
        #     name=a.get('name')
        #     price=a.get('price')
        #     if name != price:
        #         raise ValidationError('错了')
        #     else:
        #         return a
    使用第二种后面还可以跟着写局部钩子和全局钩子用于反序列化

    最后视图函数调用序列化的内容并返回给前端进行渲染处理

    在View视图层操作:
    
     查询多本书的方法:
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from app.models import Book
    from app.Myserialize import Bookserializer
    
    
    class Books(APIView):  # 这个是获取多本书的接口
    
        def get(self, request, *args, **kwargs):  # 这里是通过对drf框架 使用cbv 的get请求
            response = {'status': 100, 'msg': '获取成功'}  # 设置发送出去response 信息
            book_list = Book.objects.all()
            book_ser = Bookserializer(book_list, many=True)  # 使用drf 实例化 自定义的Bookserializer 来实例化
            response['data'] = book_ser.data  # 把实例化book_ser 的data数据放入 response['data']中
            return Response(response)  # 在使用Response来返回出去
    
        def post(self, request):        #这个是添加书的接口
            response = {'status': 100, 'msg': '添加成功'}
    
            try:
                book_ser = Bookserializer(data=request.data)
                if book_ser.is_valid():         #这里就是晕倒的反序列的内部工具和钩子判断
                    book_ser.save()
                    response['data'] = book_ser.data    #判断通过吧数据返回出去
                else:
                    response['msg'] = book_ser.errors
            except Exception as e:
                response['msg'] = str(e)
            return Response(response)
    简单的调用序列化好的内容,并反馈给前端消息
    class BookView(APIView):        #获取单本图书的接口
        def get(self, request, pk,*args, **kwargs):
            response = {'status': 100, 'msg': '获取成功'}
            #取到pk为传入的pk的书,book对象
            book = models.Book.objects.all().filter(pk=pk).first()
            #要序列化单条,many=False
            book_ser=BookSerializer(instance=book,many=False)
            # book_ser=BookSerializer(book,many=False)
            response['data']=book_ser.data
    
    
            return Response(response)
    
    
        def put(self,request,pk):     #修改某本书
            response = {'status': 100, 'msg': '修改'}
            book=models.Book.objects.filter(pk=pk).first()
            #修改
            book_ser = BookSerializer(instance=book,data=request.data)
            if book_ser.is_valid():
                book_ser.save()
                response['data']=book_ser.data
            else:
                response['msg']=book_ser.errors
            return Response(response)
    接口显示单个内容 ,主要PK是关键点
    在路由层的配置:
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^books/$', views.BooksView.as_view()),    #查看全部书的接口
        url(r'^books/(?P<pk>d+)', views.BookView.as_view()),   #查看单个书的接口
    ]
    在urls 路由层进行判断

    #总结,个人建议使用第二种序列化的方法,这样对反序列化有很好的帮助


    以下是全部的接口信息
    
    from  app import  models
    from  app.Myserializers import  BookSerializers
    
    # Create your views here.
    from rest_framework.views import  APIView
    from rest_framework.response import Response
    
    
    
    class Booksview(APIView):
    
        def get(self,request,*args,**kwargs):       #获取多本书
            response = {'status':100, 'msg':'查询成功'}
            book_list = models.Book.objects.all()
            book_ser = BookSerializers(book_list,many=True)
            response['data'] = book_ser.data
            return Response(response)
    
        def post(self,request):                     #添加书
            response = {'status':100, 'msg':'添加成功'}
            try:
                book_ser = BookSerializers(data=request.data)   #序列化工具拿到的数据是在request.data内的字典中获取
                if book_ser.is_valid(): #进行钩子判断与基础验证
                    book_ser.save()
                    response['data'] =book_ser.data
                else:
                    response['msg']= book_ser.errors
            except Exception as e:
                response['msg'] =str(e)
            return  Response(response)
    
    class Bookview(APIView):
    
        def get(self, request, pk, *args, **kwargs):        #获取单本书的接口
            response = {'status':100 , 'msg': '获取成功'}
            book = models.Book.objects.all().filter(pk=pk).first()
            book_ser = BookSerializers(instance=book,many=False)
            response['data'] = book_ser.data
            return  Response(response)
    
        def put(self, request,pk):          #修改但本书的接口
            response = {'status':100, 'msg':'修改成功'}
            book = models.Book.objects.filter(pk=pk).first()
            book_ser = BookSerializers(instance=book,data=request.data)
            if book_ser.is_valid():
                book_ser.save()
                response['data']= book_ser.data
            else:
                response['msg']= book_ser.errors
            return  Response(response)
    
        def delete(self,request,pk):        #删除的接口
            response = {'status':100, 'msg': '删除成功'}
            book = models.Book.objects.filter(pk=pk).delete()
            return Response(response)
    以下是通过cbv实现的简单的五种请求的接口实现方式
  • 相关阅读:
    配置.net 3.0开发环境
    SQL分页语句
    SQL注入的实现原理和防范
    asp.net页面缓存技术
    内网渗透基础
    内网渗透工作组信息收集
    ORA00702: bootstrap verison ” inconsistent with version ’8.0.0.0.0′
    我的新blog
    专业Oracle数据库恢复技术支持
    高等代数第2讲——n元线性方程组解的情况
  • 原文地址:https://www.cnblogs.com/gukai/p/10780292.html
Copyright © 2020-2023  润新知