Django 序列化

这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战

一、简介

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

便于展现的序列化操作,我们需要在model添加外键、多对多情况。以下是新的models(请删除原有的数据库,重新migrate):

models.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Python复制代码from django.db import models

class UserInfo(models.Model):
user_type_choice = (
(1,"普通用户"),
(2,"会员"),
)
user_type = models.IntegerField(choices=user_type_choice)
username = models.CharField(max_length=32,unique=True)
password = models.CharField(max_length=64)
group = models.ForeignKey(to='UserGroup',null=True,blank=True)
roles = models.ManyToManyField(to='Role')


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



class UserGroup(models.Model):
"""用户组"""
name = models.CharField(max_length=32,unique=True)


class Role(models.Model):
"""角色"""
name = models.CharField(max_length=32,unique=True)

二、使用

1.基本使用

在urls.py中添加新的角色url,以前的url为了减少干扰,在这里进行注释:

1
2
3
4
5
6
7
8
9
Python复制代码from django.conf.urls import url
from app01 import views

urlpatterns = [

# url(r'^api/v1/auth', views.AuthView.as_view()),# url(r'^api/v1/order', views.OrderView.as_view()),
url(r'^api/v1/roles', views.RoleView.as_view()), # 角色视图
# url(r'^api/(?P<version>[v1|v2]+)/user', views.UserView.as_view(),name="user_view"),
]

views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Python复制代码from rest_framework import serializers
from rest_framework.views import APIView
from django.shortcuts import HttpResponse
from app01 import models
import json


class RolesSerializer(serializers.Serializer): #定义序列化类
id=serializers.IntegerField() #定义需要提取的序列化字段,名称和model中定义的字段相同
name=serializers.CharField()
class RoleView(APIView):
"""角色"""
def get(self,request,*args,**kwargs):
roles=models.Role.objects.all()
res=RolesSerializer(instance=roles,many=True) #instance接受queryset对象或者单个model对象,当有多条数据时候,使用many=True,单个对象many=Falsereturn HttpResponse(json.dumps(res.data,ensure_ascii=False))

使用浏览器访问http://127.0.0.1:8000/api/v1/roles ,结果如下:

2.自定义序列化字段

当数据模型中有外键或者多对多时候,这时候就需要自定义序列化了

新增用户信息url

1
2
3
4
5
6
7
8
9
10
Python复制代码from django.conf.urls import url
from app01 import views

urlpatterns = [

# url(r'^api/v1/auth', views.AuthView.as_view()),# url(r'^api/v1/order', views.OrderView.as_view()),
url(r'^api/v1/roles', views.RoleView.as_view()),
url(r'^api/v1/userinfo', views.UserinfoView.as_view()), #用户信息
# url(r'^api/(?P<version>[v1|v2]+)/user', views.UserView.as_view(),name="user_view"),
]

UserinfoView和序列化类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
python复制代码class UserinfoSerializer(serializers.ModelSerializer):
id = serializers.IntegerField() # 定义需要提取的序列化字段,名称和model中定义的字段相同
username=serializers.CharField()
password=serializers.CharField()
#sss=serializers.CharField(source='user_type') #该方法只能拿到user_type的ID
sss=serializers.CharField(source='get_user_type_display') #自定义字段名称,和数据模型不一致,需要指定source本质调用get_user_type_display()方法获取数据
#rl=serializers.CharField(source='roles.all.first.name')
gp=serializers.CharField(source='group.name')
rl=serializers.SerializerMethodField() #多对多序列化方法一
def get_rl(self,obj): #名称固定:get_定义的字段名称
"""
自定义序列化
:param obj:传递的model对象,这里已经封装好的
:return:
"""
roles=obj.roles.all().values() #获取所有的角色

return list(roles) #返回的结果一定有道是json可序列化的对象
class Meta:
model = models.UserInfo
fields = ['id', 'username', 'password', 'sss','rl','gp'] #配置要序列化的字段
# fields = "__all__" 使用model中所有的字段

class UserinfoView(APIView):
"""用户信息"""
def get(self,request,*args,**kwargs):
users=models.UserInfo.objects.all()
res=UserinfoSerializer(instance=users,many=True) #instance接受queryset对象或者单个model对象,当有多条数据时候,使用many=True,单个对象many=False
return HttpResponse(json.dumps(res.data,ensure_ascii=False))

访问http://127.0.0.1:8000/api/v1/userinfo ,查看结果:


除了以上的Serializer,还可以使用ModelSerializer,ModelSerializer继承了serializer,其结果和上面示例一样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
python复制代码class UserinfoSerializer(serializers.ModelSerializer):
id = serializers.IntegerField() # 定义需要提取的序列化字段,名称和model中定义的字段相同
username=serializers.CharField()
password=serializers.CharField()
#sss=serializers.CharField(source='user_type') #该方法只能拿到user_type的ID
sss=serializers.CharField(source='get_user_type_display') #自定义字段名称,和数据模型不一致,需要指定source本质调用get_user_type_display()方法获取数据
#rl=serializers.CharField(source='roles.all.first.name')
gp=serializers.CharField(source='group.name')
rl=serializers.SerializerMethodField() #多对多序列化方法一
def get_rl(self,obj): #名称固定:get_定义的字段名称
"""
自定义序列化
:param obj:传递的model对象,这里已经封装好的
:return:
"""
roles=obj.roles.all().values() #获取所有的角色

return list(roles) #返回的结果一定有道是json可序列化的对象
class Meta:
model = models.UserInfo
fields = ['id', 'username', 'password', 'sss','rl','gp'] #配置要序列化的字段
# fields = "__all__" 使用model中所有的字段

class UserinfoView(APIView):
"""用户信息"""
def get(self,request,*args,**kwargs):
users=models.UserInfo.objects.all()
res=UserinfoSerializer(instance=users,many=True) #instance接受queryset对象或者单个model对象,当有多条数据时候,使用many=True,单个对象many=False
return HttpResponse(json.dumps(res.data,ensure_ascii=False))

3.连表序列化以及深度控制

使用depth进行深度控制,越深其序列化的细读越高

1
2
3
4
5
6
7
8
9
10
11
12
13
python复制代码class UserinfoSerializer(serializers.ModelSerializer):

class Meta:
model = models.UserInfo
#fields = "__all__" # 使用model中所有的字段
fields = ['id', 'username', 'password', 'group','roles'] # 配置要序列化的字段
depth = 1 #系列化深度,1~10,建议使用不超过3
class UserinfoView(APIView):
"""用户信息"""
def get(self,request,*args,**kwargs):
users=models.UserInfo.objects.all()
res=UserinfoSerializer(instance=users,many=True) #instance接受queryset对象或者单个model对象,当有多条数据时候,使用many=True,单个对象many=False
return HttpResponse(json.dumps(res.data,ensure_ascii=False))

请求http://127.0.0.1:8000/api/v1/userinfo ,结果如下:

4.序列化字段url

urls.py新加入组url

1
2
3
4
5
6
7
8
python复制代码urlpatterns = [

# url(r'^api/v1/auth', views.AuthView.as_view()),# url(r'^api/v1/order', views.OrderView.as_view()),
url(r'^api/v1/roles', views.RoleView.as_view()),
url(r'^api/v1/userinfo', views.UserinfoView.as_view()),
url(r'^api/v1/group/(?P<xxx>\d+)', views.GroupView.as_view(),name='gp'), # 新加入组url
# url(r'^api/(?P<version>[v1|v2]+)/user', views.UserView.as_view(),name="user_view"),
]

views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
python复制代码class UserinfoSerializer(serializers.ModelSerializer):
group=serializers.HyperlinkedIdentityField(view_name='gp',lookup_field='group_id',lookup_url_kwarg='xxx')
#view_name,urls.py目标url的视图别名(name),这里是UserGroup的视图别名
#lookup_field 给url传递的参数,也就是正则匹配的字段
#lookup_url_kwarg,url中正则名称,也就是kwargs中的key
class Meta:
model = models.UserInfo
#fields = "__all__" # 使用model中所有的字段
fields = ['id', 'username', 'password','roles','group'] # 配置要序列化的字段
depth = 1 #系列化深度,1~10,建议使用不超过3
class UserinfoView(APIView):
"""用户信息"""
def get(self,request,*args,**kwargs):
users=models.UserInfo.objects.all()
res=UserinfoSerializer(instance=users,many=True,context={'request': request}) #instance接受queryset对象或者单个model对象,当有多条数据时候,使用many=True,单个对象many=False
#若需生成超链接字段,则需要加context={'request': request}
return HttpResponse(json.dumps(res.data,ensure_ascii=False))

class UserGroupSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserGroup
fields = "__all__"
depth = 0


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

group_id=kwargs.get('xxx')
group_obj=models.UserGroup.objects.get(id=group_id)
res=UserGroupSerializer(instance=group_obj,many=False) #instance接受queryset对象或者单个model对象,当有多条数据时候,使用many=True,单个对象many=False
return HttpResponse(json.dumps(res.data,ensure_ascii=False))

此时访问组信息:http://127.0.0.1:8000/api/v1/group/1,结果如下:

在查看用户信息,此时生成的组就是超链接形式了(便于查看json数据,这里用postman发请求):

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%