django-rest-framework(八)(序列化)

序列化

功能

  • 功能一:序列化数据
  • 功能二:请求数据校验

序列化数据

前提概要

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('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字段时,会将souce字段中的内容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(生成连接)

urls.py

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'),
]

view.py

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("请求数据校验")

猜你喜欢

转载自blog.csdn.net/qq_33458131/article/details/83718249