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

    rest-framework之序列化组件

    一 Django自带序列化组件

    详见

    二 rest-framework序列化之Serializer

    models部分:

    复制代码
    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
    复制代码

    view部分:

    复制代码
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from .models import *
    from django.shortcuts import HttpResponse
    from django.core import serializers
    
    
    from rest_framework import serializers
    
    class BookSerializers(serializers.Serializer):
        title=serializers.CharField(max_length=32)
        price=serializers.IntegerField()
        pub_date=serializers.DateField()
        publish=serializers.CharField(source="publish.name")
        #authors=serializers.CharField(source="authors.all")
        authors=serializers.SerializerMethodField()
        def get_authors(self,obj):
            temp=[]
            for author in obj.authors.all():
                temp.append(author.name)
            return temp
      #此处可以继续用author的Serializers,
      # def get_authors(self,obj):
        # ret=obj.authors.all()
        # ss=AuthorSerializer(ret,many=True)
        # return ss.data
    class BookViewSet(APIView): def get(self,request,*args,**kwargs): book_list=Book.objects.all() # 序列化方式1: # from django.forms.models import model_to_dict # import json # data=[] # for obj in book_list: # data.append(model_to_dict(obj)) # print(data) # return HttpResponse("ok") # 序列化方式2: # data=serializers.serialize("json",book_list) # return HttpResponse(data) # 序列化方式3: bs=BookSerializers(book_list,many=True) #many=True代表有多条数据,如果只有一条数据,many=False return Response(bs.data)
         # 序列化方式4:
       # ret=models.Book.objects.all().values('nid','title')
         # dd=list(ret)
    # return HttpResponse(json.dumps(dd))


    复制代码

    注意:

    source 如果是字段,会显示字段,如果是方法,会执行方法,不用加括号(authors=serializers.CharField(source='authors.all'))

    如在模型中定义一个方法,直接可以在在source指定执行

    class UserInfo(models.Model):
        user_type_choices = (
            (1,'普通用户'),
            (2,'VIP'),
            (3,'SVIP'),
        )
        user_type = models.IntegerField(choices=user_type_choices)
    
        username = models.CharField(max_length=32,unique=True)
        password = models.CharField(max_length=64)
    
    
    #视图
    ret=models.UserInfo.objects.filter(pk=1).first()
    aa=ret.get_user_type_display()
    
    #serializer
    xx=serializers.CharField(source='get_user_type_display')
    View Code

    三 rest-framework序列化之ModelSerializer

    复制代码
    class BookSerializers(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            # fields = "__all__"
            fields=['nid','title','authors','publish']
            # exclude=('nid',)   #不能跟fields同时用
            # depth = 1    #深度控制,写 几 往里拿几层,层数越多,响应越慢,官方建议0--10之间,个人建议最多3层
        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(极少数)

    复制代码
    class BookSerializers(serializers.ModelSerializer):
        class Meta:
            model = models.Book
            fields = "__all__"
        # 生成连接,直接查看出版社详情
        publish = serializers.HyperlinkedIdentityField(view_name='ttt', lookup_field='publish_id', lookup_url_kwarg='pkk')
        authors=serializers.SerializerMethodField()
        def get_authors(self,obj):
            ret=obj.authors.all()
            ss=AuthorSerializer(ret,many=True)
            return ss.data
    #--------------

    res=BookSerializers(ret,many=True,context={'request': request})
    #--------------
    class Publish(APIView): def get(self,request,pkk): print(pkk) return HttpResponse('ok') #----路由--- url(r'^publish/(?P<pkk>d+)$', views.Publish.as_view(),name='ttt'),
    复制代码

     五 序列化组件之请求数据校验和保存功能

    复制代码
    class BookSerializers(serializers.ModelSerializer):
        class Meta:
            model=Book
            fields="__all__"
    
    #————————
    class BookView(APIView):
    
        def post(self, request):
    
            # 添加一条数据
            print(request.data)
    
            bs=BookSerializers(data=request.data)
            if bs.is_valid():
                bs.save()  # 生成记录
                return Response(bs.data)
            else:
    
                return Response(bs.errors)
    复制代码
    class BookSerializer1(serializers.Serializer):
        title=serializers.CharField(error_messages={'required': '标题不能为空'})
    
    #这种方式要保存,必须重写create方法

     通过源码查看留的校验字段的钩子函数:

    复制代码
        
    #is_valid---->self.run_validation-(执行Serializer的run_validation)-->self.to_internal_value(data)---(执行Serializer的run_validation:485行)
    def validate_title(self, value): from rest_framework import exceptions raise exceptions.ValidationError('看你不顺眼') return value

    #全局
    def validate(self, attrs):
    from rest_framework import exceptions
    if attrs.get('title')== attrs.get('title2'):
    return attrs
    else:
    raise exceptions.ValidationError('不想等啊')
    复制代码

    序列化组件源码分析

    序列化组件,先调用__new__方法,如果many=True,生成ListSerializer对象,如果为False,生成Serializer对象
    序列化对象.data方法--调用父类data方法---调用对象自己的to_representation(自定义的序列化类无此方法,去父类找)
    Aerializer类里有to_representation方法,for循环执行attribute = field.get_attribute(instance)
    再去Field类里去找get_attribute方法,self.source_attrs就是被切分的source,然后执行get_attribute方法,source_attrs
    当参数传过去,判断是方法就加括号执行,是属性就把值取出来
    View Code

    图书的增删查改resful接口:

    视图层:

    class BookSerializers(serializers.ModelSerializer):
        class Meta:
            model=models.Book
            fields='__all__'
    
    
    class BookView(APIView):
    
        def get(self, request):
            book_list = models.Book.objects.all()
            bs = BookSerializers(book_list, many=True)
            # 序列化数据
    
            return Response(bs.data)
    
        def post(self, request):
            # 添加一条数据
            print(request.data)
    
            bs=BookSerializers(data=request.data)
            if bs.is_valid():
                bs.save()  # 生成记录
                return Response(bs.data)
            else:
    
                return Response(bs.errors)
    
    class BookDetailView(APIView):
        def get(self,request,pk):
            book_obj=models.Book.objects.filter(pk=pk).first()
            bs=BookSerializers(book_obj,many=False)
            return Response(bs.data)
        def put(self,request,pk):
            book_obj = models.Book.objects.filter(pk=pk).first()
    
            bs=BookSerializers(data=request.data,instance=book_obj)
            if bs.is_valid():
                bs.save() # update
                return Response(bs.data)
            else:
                return Response(bs.errors)
        def delete(self,request,pk):
            models.Book.objects.filter(pk=pk).delete()
    
            return Response("")
    View Code

    路由:

        url(r'^books/$', views.BookView.as_view()),
        url(r'^books/(?P<pk>d+)$', views.BookDetailView.as_view()),
    View Code
  • 相关阅读:
    Windows性能计数器应用
    Azure Oracle Linux VNC 配置
    Azure 配置管理系列 Oracle Linux (PART6)
    Azure 配置管理系列 Oracle Linux (PART5)
    Azure 配置管理系列 Oracle Linux (PART4)
    Azure 配置管理系列 Oracle Linux (PART3)
    Azure 配置管理系列 Oracle Linux (PART2)
    vagrant多节点配置
    docker基本操作
    LINUX开启允许对外访问的网络端口命令
  • 原文地址:https://www.cnblogs.com/di2wu/p/10127671.html
Copyright © 2011-2022 走看看