DRF笔记七——序列化

序列化

继承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('提交数据')
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值