序列化
继承serializers.Serializer
-
基本使用:
# model.py from django.db import models class Role(models.Model): title = models.CharField(max_length=32)
# url.py from django.conf.urls import url from api import views urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/roles/$', views.RolesView.as_view()), ]
# view.py from rest_framework import serializers from api import models class RolesSerializer(serializers.Serializer): id = serializers.IntegerField() title = serializers.CharField() class RolesView(APIView): def get(self, request, *args, **kwargs): # 方式一(原生实现方式,不借助DRF序列器) # roles = models.Role.objects.all().values('id', 'title') # roles = list(roles) # ret = json.dumps(roles, ensure_ascii=False) # 方式二:对于[obj, obj, obj] # roles = models.Role.objects.all().all() # # many=True表示有多条数据 # ser = RolesSerializer(instance=roles, many=True) # ret = json.dumps(ser.data, ensure_ascii=False) # 方式三:转换单个对象 role = models.Role.objects.all().first() # many=False表示有一条数据 ser = RolesSerializer(instance=role, many=False) # ser.data已经是转换完成后的结果 ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret)
-
自定义字段,配合source使用
# model.py from django.db import models class UserGroup(models.Model): title = models.CharField(max_length=32) class Role(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(to='UserGroup', on_delete=models.DO_NOTHING) roles = models.ManyToManyField('Role')
# url.py from django.conf.urls import url from api import views urlpatterns = [ url(r'^(?P<version>[v1|v2]+)/userinfo/$', views.UserInfoView.as_view()), ]
#view.py from rest_framework import serializers from api import models class UserInfoSerializer(serializers.Serializer): user_type1 = serializers.IntegerField(source='user_type') user_type_choices1 = serializers.CharField(source='get_user_type_display') username = serializers.CharField() password = serializers.CharField() gp = serializers.CharField(source='group.title') # rls = serializers.CharField(source='roles.all') rls = serializers.SerializerMethodField() # 自定义显示,显示的内容为一个函数返回值(gte开头,该字段结尾的函数) def get_rls(self, row): role_obi_list = row.roles.all() ret = [] for item in role_obi_list: ret.append({'id': item.id, 'title': item.title}) return ret class UserInfoView(APIView): def get(self, request, *args, **kwargs): users = models.UserInfo.objects.all() ser = UserInfoSerializer(users, many=True) ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret)
继承serializers.ModelSerializer
# url.py
from django.conf.urls import url
from api import views
urlpatterns = [
url(r'^(?P<version>[v1|v2]+)/userinfofo/$', views.UserInfofoView.as_view()),
]
#view.py
from rest_framework import serializers
from api import models
class UserInfofoSerializer(serializers.ModelSerializer):
user_type1 = serializers.IntegerField(source='user_type')
user_type_choices1 = serializers.CharField(source='get_user_type_display')
gp = serializers.CharField(source='group.title')
rls = serializers.SerializerMethodField() # 自定义显示,显示的内容为一个函数返回值(gte开头,该字段结尾的函数)
class Meta:
model = models.UserInfo
# 直接按数据库中的字段显示
# fields = "__all__"
fields = ['id', 'username', 'password', 'user_type1', 'user_type_choices1', 'rls', 'gp']
def get_rls(self, row):
role_obi_list = row.roles.all()
ret = []
for item in role_obi_list:
ret.append({'id': item.id, 'title': item.title})
return ret
class UserInfofoView(APIView):
def get(self, request, *args, **kwargs):
users = models.UserInfo.objects.all()
ser = UserInfofoSerializer(users, many=True)
ret = json.dumps(ser.data, ensure_ascii=False)
return HttpResponse(ret)
自动序列化连表,使用depth字段实现深度展示
# url.py
from django.conf.urls import url
from api import views
urlpatterns = [
url(r'^(?P<version>[v1|v2]+)/userin/$', views.UserInView.as_view()),
]
#view.py
from rest_framework import serializers
from api import models
class UserInSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
# 直接按数据库中的字段显示
# fields = "__all__"
fields = ['id', 'username', 'password', 'group', 'roles']
depth = 1 # 深度展示层数(官方建议0-10层),当表格中某些字段使用ForeignKey或ManyToManyField时,depth=1,表示把与UserInfo表相关联的一层数据全都拿到,不建议使用太多层,会影响速度。
class UserInView(APIView):
def get(self, request, *args, **kwargs):
users = models.UserInfo.objects.all()
ser = UserInSerializer(users, many=True)
ret = json.dumps(ser.data, ensure_ascii=False)
return HttpResponse(ret)
生成URL链接HyperlinkedIdentityField
#url
from django.conf.urls import url
from api import views
urlpatterns = [
url(r'^(?P<version>[v1|v2]+)/userin/$', views.UserInView.as_view()),
url(r'^(?P<version>[v1|v2]+)/group/(?P<pk>\d+)$', views.GroupView.as_view(), name='gp'),
]
#view
from rest_framework import serializers
from api import models
class UserInSerializer(serializers.ModelSerializer):
group = serializers.HyperlinkedIdentityField(view_name='gp', lookup_url_kwarg='pk', lookup_field='group_id')
class Meta:
model = models.UserInfo
# 直接按数据库中的字段显示
# fields = "__all__"
fields = ['id', 'username', 'password', 'group', 'roles']
depth = 1 # 深度展示层数(官方建议0-10层),当表格中某些字段使用ForeignKey或ManyToManyField时,depth的值,代表想深度展示的层数
class UserInView(APIView):
def get(self, request, *args, **kwargs):
users = models.UserInfo.objects.all()
ser = UserInSerializer(users, many=True, context={'request': request})
ret = json.dumps(ser.data, ensure_ascii=False)
return HttpResponse(ret)
class GroupViewSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserGroup
# 直接按数据库中的字段显示
fields = "__all__"
class GroupView(APIView):
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk')
obj = models.UserGroup.objects.filter(pk=pk).first()
ser = GroupViewSerializer(obj, many=False)
ret = json.dumps(ser.data, ensure_ascii=False)
return HttpResponse(ret)
源码
如果是单个对象,交个Serializers类处理;
如果是QuerySet,交给ListSerializer类处理;
入口函数:serializers对象.data
# 1、实例化,将数据封装到对象,先执行__new__,再执行__init__
'''
如果many=True,执行ListSerializer对象的构造方法;
如果many=False,执行UserInSerializer对象的构造方法;
'''
ser = UserInSerializer(users, many=True, context={'request': request})
# 2、调用对象的data属性
# 执行ListSerializer中to_representation方法
# 执行UserInSerializer,先执行Serializer中to_representation方法,循环执行UserInSerializer中所有需要序列化的字段,获取指定字段对应的值或对象,如果是CharField或IntegerField获取的是值,如果HyperlinkedIdentityField获取的是对象;再分别执行各个子段对应的to_representation方法。
ret = json.dumps(ser.data, ensure_ascii=False)
小总结
1、写类,可以继承serializers.Serializer或serializers.ModelSerializer
class UserInfoSerializer(serializers.Serializer):
username = serializers.CharField()
password = serializers.CharField()
class UserInfofoSerializer(serializers.ModelSerializer):
class Meta:
model = models.UserInfo
# 直接按数据库中的字段显示
# fields = "__all__"
fields = ['id', 'username', 'password']
2、字段(可以自定义)
-
a、通过source字段
title = serializers.CharField(source=‘xxx.xxx.xxx’)
class UserInfoSerializer(serializers.Serializer):
gp = serializers.CharField(source='group.title')
-
b、通过serializers.SerializerMethodField(),并自定义显示方法
title = serializers.SerializerMethodField()
class UserInfoSerializer(serializers.Serializer):
rls = serializers.SerializerMethodField() # 自定义显示,显示的内容为一个函数返回值(gte开头,该字段结尾的函数)
# 自定义方法
def get_rls(self, row):
role_obi_list = row.roles.all()
ret = []
for item in role_obi_list:
ret.append({'id': item.id, 'title': item.title})
return ret
-
c、自动序列化连表(depth)
class UserInSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo # 直接按数据库中的字段显示 # fields = "__all__" fields = ['id', 'username', 'password', 'group', 'roles'] depth = 1 # 深度展示层数(官方建议0-10层),当表格中某些字段使用ForeignKey或ManyToManyField时,depth的值,代表想深度展示的层数 class UserInView(APIView): def get(self, request, *args, **kwargs): users = models.UserInfo.objects.all() ser = UserInSerializer(users, many=True) ret = json.dumps(ser.data, ensure_ascii=False) return HttpResponse(ret)
请求数据校验
# url.py
from django.conf.urls import url
from api import views
urlpatterns = [
url(r'^(?P<version>[v1|v2]+)/usergroup/$', views.UserGroupView.as_view()),
]
# view.py
from rest_framework import serializers
from api import models
#自定义验证规则的类
class TitleValidator(object):
def __init__(self, base):
self.base = base
def __call__(self, value):
if not value.startswith(self.base):
message = '标题必须是以%s开头' % self.base
raise serializers.ValidationError(message)
def set_context(self, serializer_field):
"""
This hook is called by the serializer instance,
prior to the validation call being made.
"""
# 执行验证之前调用,serializer_fields是当前字段对象
pass
class UserGroupSerializer(serializers.Serializer):
# validators自定义验证规则
title = serializers.CharField(error_messages={"required": "不能为空"}, validators=[TitleValidator('老男人'), ])
# 自定义钩子函数
# 可以返回值,也可抛出异常
def validate_title(self, value):
print(value)
# from rest_framework import exceptions
# raise exceptions.ValidationError('就是不通过')
return value
class UserGroupView(APIView):
def post(self, request, *args, **kwargs):
'''
对提交的数据进行数据校验
:param request:
:param args:
:param kwargs:
:return:
'''
# 获取提交的数据
print(request.data)
ser = UserGroupSerializer(data=request.data)
if ser.is_valid():
print(ser.validated_data['title'])
else:
print(ser.errors)
return HttpResponse('提交数据')