序列化
功能:
- 功能一:序列化数据
- 功能二:请求数据校验
序列化数据
前提概要
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('UserGroup', on_delete=models.CASCADE)
roles = models.ManyToManyField('Role')
class UserToken(models.Model):
user = models.OneToOneField(to='UserInfo', on_delete=models.CASCADE)
token = models.CharField(max_length=64)
基本使用1:继承Serializer类
class UserinfoSerializer(serializers.Serializer):
username = serializers.CharField()
password = serializers.CharField()
class UserinfoView(APIView):
def get(self, request, *args, **kwargs):
user =UserInfo.objects.all()
ser = UserinfoSerializer(instance=user, many=True)
set = json.dumps(ser.data, ensure_ascii=False)
return HttpResponse(set)
source的用法
当遇到source字段时,会将source字段中的内容split("."),然后依次调用
获取用户类型的ID、内容、所属组
class UserinfoSerializer(serializers.Serializer):
# 获取数据库中用户类型ID
# 使用source的原理是实现row.user_type即是获取用户的类型ID
usertype = serializers.CharField(source='user_type')
# 获取用户类型内容
# 使用source的原理是实现row.get_user_type_display()即调用了该行元素的方法,获取到内容
usertype_content = serializers.CharField(source='get_user_type_display')
# 获取用户所属组
group = serializers.CharField(source='group.title')
username = serializers.CharField()
password = serializers.CharField()
结果
[
{
"usertype": "1",
"usertype_content": "普通用户",
"group": "1组",
"username": "小红",
"password": "123"
},
{
"usertype": "2",
"usertype_content": "VIP",
"group": "2组",
"username": "小明",
"password": "123"
},
{
"usertype": "3",
"usertype_content": "SVIP",
"group": "1组",
"username": "小王",
"password": "123"
}
]
自定义序列化类
获取用户喜欢的角色
class UserinfoSerializer(serializers.Serializer):
# 获取数据库中用户类型ID
# 使用source的原理是实现row.user_type即是获取用户的类型ID
usertype = serializers.CharField(source='user_type')
# 获取用户类型内容
# 使用source的原理是实现row.get_user_type_display()即调用了改行元素的方法,获取到内容
usertype_content = serializers.CharField(source='get_user_type_display')
# 获取用户所属组
group = serializers.CharField(source='group.title')
username = serializers.CharField()
password = serializers.CharField()
rls = serializers.SerializerMethodField()
# 函数名为get_ + rls(上面定义的字段名)
def get_rls(self, row):
role = row.roles.all()
ret = list()
for item in role:
ret.append({'id': item.id, 'title': item.title})
# 返回想要的内容
return ret
结果
[
{
"usertype": "1",
"usertype_content": "普通用户",
"group": "1组",
"username": "小红",
"password": "123",
"rls": [
{
"id": 1,
"title": "老师"
},
{
"id": 2,
"title": "医生"
},
{
"id": 3,
"title": "护士"
}
]
},
{
"usertype": "2",
"usertype_content": "VIP",
"group": "2组",
"username": "小明",
"password": "123",
"rls": [
{
"id": 1,
"title": "老师"
},
{
"id": 3,
"title": "护士"
}
]
},
{
"usertype": "3",
"usertype_content": "SVIP",
"group": "1组",
"username": "小王",
"password": "123",
"rls": []
}
]
基本使用二:继承ModelSerializer类
示例一
class UserinfoSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo
fields = "__all__"
示例二
class UserinfoSerializer(serializers.ModelSerializer):
usertype_content = serializers.CharField(source='get_user_type_display')
rls = serializers.SerializerMethodField()
class Meta:
model = UserInfo
# 获取所有字段
# fields = "__all__"
# 自定义选择字段
fields = ['id', 'username', 'password', 'user_type', 'usertype_content',]
def get_rls(self, row):
role = row.roles.all()
ret = list()
for item in role:
ret.append({'id': item.id, 'title': item.title})
return ret
自动序列化链表操作
class UserinfoSerializer(serializers.ModelSerializer):
class Meta:
model = UserInfo
# 获取所有字段
fields = "__all__"
# 深度,建议在0-3之间,获取外键之后的多层数据
depth = 1
结果
[
{
"id": 1,
"user_type": 1,
"username": "小红",
"password": "123",
"group": {
"id": 1,
"title": "1组"
},
"roles": [
{
"id": 1,
"title": "老师"
},
{
"id": 2,
"title": "医生"
},
{
"id": 3,
"title": "护士"
}
]
},
{
"id": 2,
"user_type": 2,
"username": "小明",
"password": "123",
"group": {
"id": 2,
"title": "2组"
},
"roles": [
{
"id": 1,
"title": "老师"
},
{
"id": 3,
"title": "护士"
}
]
},
{
"id": 3,
"user_type": 3,
"username": "小王",
"password": "123",
"group": {
"id": 1,
"title": "1组"
},
"roles": []
}
]
Hyperlinked(生成连接)
from django.conf.urls import url
from api import views
app_name = 'api'
urlpatterns = [
url(r'^(?P<version>[v1|v2]+)/user/$', views.UserView.as_view(), name='user'),
url(r'^(?P<version>[v1|v2]+)/userinfo/$', views.UserinfoView.as_view(), name='userinfo'),
url(r'^(?P<version>[v1|v2]+)/group/(?P<pk>\d+)$', views.GroupinfoView.as_view(), name='gp'),
]
from django.shortcuts import render, HttpResponse
from rest_framework.views import APIView
from api.models import UserInfo, UserToken, Role, UserGroup
from rest_framework import serializers
import json
class UserinfoSerializer(serializers.ModelSerializer):
# 生成链接的字段
# lookup_url_kwarg指的是urls.py的pk;lookup_field指的是组的id号;view_name指的是urls.py的name
group = serializers.HyperlinkedIdentityField(view_name='gp',lookup_field='group_id', lookup_url_kwarg='pk')
class Meta:
model = UserInfo
# 获取所有字段
# fields = "__all__"
# 自定义选择字段
fields = ['id', 'username', 'password', 'group']
class UserinfoView(APIView):
def get(self, request, *args, **kwargs):
user =UserInfo.objects.all()
ser = UserinfoSerializer(instance=user, many=True, context={'request': request})
set = json.dumps(ser.data, ensure_ascii=False)
return HttpResponse(set)
class GroupinfoSerializer(serializers.ModelSerializer):
class Meta:
model = UserGroup
fields = "__all__"
class GroupinfoView(APIView):
def get(self, request, *args, **kwargs):
pk = kwargs.get("pk")
group = UserGroup.objects.filter(id=pk).first()
ser = GroupinfoSerializer(instance=group, many=False)
ret = json.dumps(ser.data, ensure_ascii=False)
return HttpResponse(ret)
请求数据校验
简单示例
class UserinfoSerializer(serializers.Serializer):
# username字段不能为空
username = serializers.CharField(error_messages={'blank': '用户名不能为空'})
class UserinfoView(APIView):
def post(self, request, *args, **kwargs):
# print(request.data)
ser = UserinfoSerializer(data=request.data)
if ser.is_valid():
print(ser.validated_data)
else:
print(ser.errors['username'][0])
return HttpResponse("请求数据校验")
自定义验证规则
class StartwithValidators(object):
def __init__(self, base):
self.base = base
def __call__(self, value):
if not value.startswith(self.base):
raise serializers.ValidationError('用户名必须以%s开头' % self.base)
def set_context(self, serializer_field):
pass
class UserinfoSerializer(serializers.Serializer):
# 该字段名必须以wang开头
username = serializers.CharField(error_messages={'blank': '用户名不能为空'}, validators=[StartwithValidators('wang')])
class UserinfoView(APIView):
def post(self, request, *args, **kwargs):
# print(request.data)
ser = UserinfoSerializer(data=request.data)
if ser.is_valid():
print(ser.validated_data)
else:
print(ser.errors['username'][0])
return HttpResponse("请求数据校验")
内置的校验函数
class UserinfoSerializer(serializers.Serializer):
username = serializers.CharField(error_messages={'blank': '用户名不能为空'})
#内置钩子函数,对字段进行校验
#函数名为‘validate_’+字段名 的形式,内部要有返回的值,否则返回None
def validate_username(self, value):
if not value.startswith('wang'):
raise serializers.ValidationError('用户名必须以wang开头')
else:
return value
class UserinfoView(APIView):
def post(self, request, *args, **kwargs):
ser = UserinfoSerializer(data=request.data)
if ser.is_valid():
print(ser.validated_data)
else:
print(ser.errors['username'][0])
return HttpResponse("请求数据校验")