• 261 第八篇:Django 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
  • 相关阅读:
    【Thinking in Java, 4e】初始化与清理
    【Thinking in Java, 4e】控制流程执行
    【Beginning Python】抽象(未完)
    【Python】装饰器 & 偏函数
    【c++ primer, 5e】函数声明 & 分离式编译
    【Python】闭包 & 匿名函数
    【c++ primer, 5e】【函数基础】
    【Python】高阶函数
    变相的取消Datagridview控件的选中状态
    NotifyICon控件使用
  • 原文地址:https://www.cnblogs.com/abdm-989/p/12168489.html
Copyright © 2020-2023  润新知