Django rest_framework之序列化(serializers)

简介

django rest framework 中的序列化组件,可以说是其核心组件,也是我们平时使用最多的组件,它不仅仅有序列化功能,更提供了数据验证的功能(与django中的form类似)。

APIView序列化的基本使用

model.py:

from django.db import models

class Idc(models.Model):
    name    = models.CharField("机房名称",max_length=32)
    address    = models.CharField("机房地址",max_length=256)
    phone     = models.CharField("联系人",max_length=15)
    email     = models.EmailField("邮件地址",default="null")
    letter    = models.CharField("IDC简称",max_length=5)

    def __str__(self):
        return self.name

    class Meta:
        db_table = "resources_idc"

序列化:

from rest_framework import serializers
from rest_framework import status
from .models import Idc

class IdcSerializer(serializers.Serializer):
    """
    Idc序列化类
    """
    id          = serializers.IntegerField()
    name        = serializers.CharField()
    address     = serializers.CharField()
    phone       = serializers.CharField()
    email       = serializers.CharField()
    letter      = serializers.CharField()

    def create(self, validated_data):
        """创建用户请求过来的数据"""
        return Idc.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """序列化更新用户过来的数据"""
        instance.name = validated_data['name']
        instance.address = validated_data['address']
        instance.phone = validated_data['phone']
        instance.email = validated_data['email']
        instance.letter = validated_data['letter']
        instance.save()
        return instance

使用APIView

from django.shortcuts import render
from rest_framework.response import Response
from rest_framework import status
from rest_framework.views import APIView
from .models import Idc
from .serializers import IdcSerializer


class IdcList(APIView):
    def get(self,request):
        """获取所有数据"""
        queryset = Idc.objects.all()
        serializer = IdcSerializer(queryset,many=True)
        return Response(serializer.data)

    def post(self,request):
        """创建数据"""
        serializer = IdcSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors)

class IdcDetail(APIView):

    def get(self,request,id):
        """获取某一条数据"""
        idc = Idc.objects.get(id=id)
        serializer = IdcSerializer(idc)
        return Response(serializer.data)

    def put(self,request,id):
        """更新某一条数据"""
        idc = Idc.objects.get(id=id)
        serializer = IdcSerializer(idc,data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors)

    def delete(self,request,id):
        idc = Idc.objects.get(id=id)
        idc.delete()

 使用mixins类

from rest_framework import mixins,generics
class IdcList_v4(generics.GenericAPIView,
                 mixins.ListModelMixin, #ListModelMixin相当于get,展示所有列表
                 mixins.CreateModelMixin): #CreateModelMixin当当于post,创建数据
    
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer

    def get(self,request,*args,**kwargs):
        """获取所有数据"""
        return self.list(request,*args,**kwargs)

    def post(self,request,*args,**kwargs):
        """创建数据"""
        return self.create(request,*args,**kwargs)


class IdcDetail_v4(generics.GenericAPIView,
                   mixins.RetrieveModelMixin,#RetrieveModelMixin相当于get,指定某条记录
                   mixins.UpdateModelMixin, #UpdateModelMixin相当于put,修改某条数据
                   mixins.DestroyModelMixin): #DestroyModelMixin相当于delete,删除某条记录

    queryset = Idc.objects.all()
    serializer_class = IdcSerializer
    lookup_field = "id" #URL关键字参数

    def get(self,request,*args,**kwargs):
        """获取某一条数据"""
        return self.retrieve(request,*args,**kwargs)

    def put(self,request,*args,**kwargs):
        """更新某一条数据"""
        return self.update(request,*args,**kwargs)

    def delete(self,request,*args,**kwargs):
        """删除数据"""
        return self.destroy(request,*args,**kwargs)

 使用mixnis混合高级版

view.py

class IdcList_v5(generics.ListCreateAPIView):
    #ListCreateAPIView相当于get与post的混合使用,可以列出所有数据,创建新的数据
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer


class IdcDetail_v5(generics.RetrieveUpdateDestroyAPIView):
    #RetrieveUpdateDestroyAPIView相当于get某一条数据,put某一条数据,delete某一条数据
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer
    lookup_field = "id" #URL关键字参数

serializers.py

from rest_framework import serializers
from rest_framework import status
from .models import Idc

class IdcSerializer(serializers.Serializer):
    """
    Idc序列化类
    """
    id          = serializers.IntegerField()
    name        = serializers.CharField()
    address     = serializers.CharField()
    phone       = serializers.CharField()
    email       = serializers.CharField()
    letter      = serializers.CharField()

    def create(self, validated_data):
        """创建用户请求过来的数据"""
        return Idc.objects.create(**validated_data)

    def update(self, instance, validated_data):
        """序列化更新用户过来的数据"""
        instance.name = validated_data['name']
        instance.address = validated_data['address']
        instance.phone = validated_data['phone']
        instance.email = validated_data['email']
        instance.letter = validated_data['letter']
        instance.save()
        return instance

更新数据:

 使用viewsets视图集

  • REST框架包括一个用于处理ViewSets的抽象,它允许开发人员集中精力对API的状态
    和交互进行建模,并根据常规约定自动处理URL构造

  • ViewSet类与View类几乎相同,不同之处在于它们提供诸如read或update之类的操作,而不是
    get或put等方法处理程序。

  • ViewSet类只绑定到一组方法处理程序,当它被实例化成一组视图的时候,通常通过使
    用一个Router类来处理自己定义的URL conf的复杂性。

from rest_framework import viewsets
class IdcListViewset(viewsets.ModelViewSet):
    queryset = Idc.objects.all()
    serializer_class = IdcSerializer
    lookup_field = "id" #URL关键字参数
ModelViewSet继承了get,put,post,delete
详情见原码
class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
源码内容

使用这种方式好处是只有一个URL,不在使用多个URL,

用传统的URL是不能用这种方式仿问

以下是URL方式:

from rest_framework.routers import DefaultRouter
route = DefaultRouter()
route.register("idcs",views.IdcListViewset)#注册你的视图

urlpatterns = [

    url(r'^',include(route.urls))
]

只有一个URL,所有IDCS的资源都可以放在这个URL里

  点进去跟其它方式一样

序列化多对一ForeignKey用户法:

class Cabinet(models.Model):
    """机柜"""
    idc     = models.ForeignKey(Idc,verbose_name="所在机房")
    name    = models.CharField(max_length=255)

    def __str__(self):
        return self.name

    class Meta:
        db_table = "resources_cabinet"
        ordering = ['id']
from django.db import models

class Idc(models.Model):
    name    = models.CharField("机房名称",max_length=32)
    address    = models.CharField("机房地址",max_length=256)
    phone     = models.CharField("联系人",max_length=15)
    email     = models.EmailField("邮件地址",default="null")
    letter    = models.CharField("IDC简称",max_length=5)

    def __str__(self):
        return self.name

    class Meta:
        db_table = "resources_idc"

serializers.py

from rest_framework import serializers
from idcs.serializers import IdcSerializer
from .models import Cabinet
from idcs.models import Idc

class CabinetSerializer(serializers.Serializer):
    """
    序列化机柜
    """
    idc  = serializers.PrimaryKeyRelatedField(many=False,queryset=Idc.objects.all())#进行多对一进行关联序列化
    #idc  = serializers.CharField(source="idc.name")
    name = serializers.CharField(required=True)

    def to_representation(self, instance):
        """把上面的成员中属性序列化成想要自己实现的json格式"""
        idc_obj = instance.idc
        print(idc_obj)
        ret = super(CabinetSerializer,self).to_representation(instance)#根据上面要显示返回的数据
        ret["idc"] = {
            "id":idc_obj.id,
            "name":idc_obj.name
        }
        return ret


    def to_internal_value(self, data):
        """
        反序列化第一步:拿到的是用户提交过来的原始数据,自己处理可以入库
        :param self:
        :param data:
        :return:
        """
        return super(CabinetSerializer,self).to_internal_value(data)


    def create(self, validated_data):
        """反序列化创建数据"""
        return Cabinet.objects.create(**validated_data)

原文地址:https://www.cnblogs.com/zhangzihong/p/9254984.html