Django rest framework(6)----序列化

为什么要序列化

django 查询数据库返回的类型是  queryset 类型 而我们和前端通信使用的大多数是json类型,这个时候我们需要把 queryset的数据类型转换成python的数据类型然后在转换成json 的格式返回

在我们没使用  restframework 中的 序列化之前我们是这样做的

class RolesView(APIView):
    def get(self,request,*args,**kwargs):
        roles = models.Role.objects.all().values('id','title')
        roles = list(roles)
        ret = json.dumps(roles,ensure_ascii=False) 
        return HttpResponse(ret)        

 json.dumps 中的参数   ensure_ascii=False 意思是不把中文进行转义,即显示中文

restframework 中的序列化器就可以自动的帮助我们 把queryset 的数据类型转化成 python的数据类型

restframework 序列化的使用

建表  models.py 

from django.db import models

class UserGroup(models.Model):
    title = models.CharField(max_length=32)


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)

    group = models.ForeignKey("UserGroup")
    roles = models.ManyToManyField("Role")


class UserToken(models.Model):
    user = models.OneToOneField(to='UserInfo')
    token = models.CharField(max_length=64)


class Role(models.Model):
    title = models.CharField(max_length=32)

 添加Role

查询所有的角色,使用  restframework进行序列化基本的使用如下

  1 写一个序列化的类继承  serializers 或  ModelSerializer ,类属性是要序列化的数据库表中的字段(注意:这个要对应)

   2 把创建序列化对象Obj,把需要序列化的数据传入进去,如果有多条数据 many = True 否则为False

   3   通过json.dumps(Obj.data) 转化成json格式

views.py 代码如下

import json
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from . import models
from rest_framework import serializers

#要先写一个序列化的类
class RolesSerializer(serializers.Serializer):
    #Role表里面的字段id和title序列化
    id = serializers.IntegerField()
    title = serializers.CharField()

class RolesView(APIView):
    def get(self,request,*args,**kwargs):
     # 方式一 多条数据的情况:
        # roles = models.Role.objects.all().values('id','title')
        # roles = list(roles)
        # ret = json.dumps(roles,ensure_ascii=False)    
        # 方式二  只有一条数据的情况
     roles = models.Role.objects.all()
        # 序列化,两个参数,instance:接受Queryset(或者对象)   mangy=True表示对Queryset进行处理,mant=False表示对对象进行进行处理
        ser = RolesSerializer(instance=roles,many=True)
        # 转成json格式,ensure_ascii=False表示显示中文,默认为True
        ret = json.dumps(ser.data,ensure_ascii=False)
        return HttpResponse(ret)   

添加对应路由

urlpatterns = [
    url(r'roles/$', views.RolesView.as_view()),
]

测试的结果如下:

 进阶使用

 上述的情况是普通的字段,如果是特殊的字段,那么我们又该如何去处理呢,我们来操作user表,表中的字段如下

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)

    group = models.ForeignKey("UserGroup")
    roles = models.ManyToManyField("Role")

  

我们使用上述的方法对其所有的字段进行序列化代码如下

class UserInfoSerializer(serializers.Serializer):
    user_type = serializers.CharField() # row.user_type
    username = serializers.CharField()
    password = serializers.CharField()
    group = serializers.CharField()
    roles = serializers.CharField()

class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):

        users = models.UserInfo.objects.all()

        # 对象, Serializer类处理; self.to_representation
        # QuerySet,ListSerializer类处理; self.to_representation
        ser = UserInfoSerializer(instance=users,many=True)
        ret = json.dumps(ser.data, ensure_ascii=False)
        return HttpResponse(ret)

为其添加路由

urlpatterns = [
    url('(?P<version>[v1|v2]+)/users/$', views.UserView.as_view(),name='uuu'),
    url(r'parser/$', views.ParserView.as_view()),
    url(r'roles/$', views.RolesView.as_view()),
    url(r'userinfo/$', views.UserInfoView.as_view()),
]

测试的结果如下

情况一  对于数据库中自已选择的字段

   对于表中的 user_type是choices(1,2,3)我们想显示全称 ,解决的方法是 传入参数source="get_user_type_display" ,它会自动的帮我们执行 get_user_type_display方法

修改后的序列化器如下

class UserInfoSerializer(serializers.Serializer):
    # user_type = serializers.CharField() # row.user_type
    user_type = serializers.CharField(source="get_user_type_display") # row.get_user_type_display()

    username = serializers.CharField()
    password = serializers.CharField()
    group = serializers.CharField()
    roles = serializers.CharField()

 测试的结果如下

 

情况二对于外键(一对一)

   对于表中外键的字段gruop ,我们想显示与其关联的title字段的内容  ,解决的方法是还是通过传入参数source="group.title"  它会自动的去查找

修改后的序列化器如下

 情况三 对于外键(多对多的情况)

   对于外键多对多的情况我们想显示其中的一些字段,这个时候由于是多对多它是一个可迭代的对象,所以不能直接向上面一对一的情况直接取,解决的方法这时候我们需要自定义方法来获取

特别需要注音的是

  1 如果  要显示外键多对多内容 要使用  roles = serializers.SerializerMethodField()  

   2  还有就是自定义函数的函数名应该是  如果多对多的外键是roles 函数名则应该是 get_roles(self,role--->可以随命名)  ,如果是rls则函数名为get_rls

代码如下

class UserInfoSerializer(serializers.Serializer):
    # user_type = serializers.CharField() # row.user_type
    user_type = serializers.CharField(source="get_user_type_display") # row.get_user_type_display()

    username = serializers.CharField()
    password = serializers.CharField()
    # group = serializers.CharField()
    group = serializers.CharField(source='group.title')
    # roles = serializers.SerializerMethodField()
    roles = serializers.SerializerMethodField()  # 自定义显示
    def get_roles(self,row):

        role_obj_list = row.roles.all()

        ret = []
        for item in role_obj_list:
            ret.append({'id':item.id,'title':item.title})
        return ret

 测试的结果如下

 ModelSerializer 序列化器的使用

 ModelSerializer 继承 的是Serializer ,所以我们在使用它的时候同样可以混合着 Serializer 使用,它主要是在序列化字段的时候做了一些简化可以简单的对字段进行批量的定义和全部序列

基本使用

class UserInfoSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.UserInfo
        fields = "__all__"  # 序列话所有的字段
        # fields = ['id','username','password','oooo','rls','group','x1']  # 对指定的字段进行批量处理

测试的结果如下

和Serializer混合使用

class UserInfoSerializer(serializers.ModelSerializer):
    oooo = serializers.CharField(source="get_user_type_display")  # row.user_type
    rls = serializers.SerializerMethodField()  # 自定义显示


    class Meta:
        model = models.UserInfo
        # fields = "__all__"
        fields = ['id','username','password','oooo','rls','group']

    def get_rls(self, row):
        role_obj_list = row.roles.all()

        ret = []
        for item in role_obj_list:
            ret.append({'id':item.id,'title':item.title})
        return ret

测试结果如下

  

猜你喜欢

转载自www.cnblogs.com/crazymagic/p/9557890.html