zoukankan      html  css  js  c++  java
  • Django rest framework(6)----序列化

    目录

    序列化

    1.继承Serializer

    基本使用 

    (1)models.py

    from django.db import models
    
    class UserInfo(models.Model):
        USER_TYPE = (
            (1,'普通用户'),
            (2,'VIP'),
            (3,'SVIP')
        )
    
        user_type = models.IntegerField(choices=USER_TYPE)
        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('UserInfo',on_delete=models.CASCADE)
        token = models.CharField(max_length=64)
    
    
    class UserGroup(models.Model):
        title = models.CharField(max_length=32)
    
    
    class Role(models.Model):
        title = models.CharField(max_length=32)

    添加Role

    (2)api/urls.py

    urlpatterns = [
        re_path('(?P<version>[v1|v2]+)/roles/', RolesView.as_view()),   #序列化
    ]

    (3)views.py

    import json
    
    from django.shortcuts import render,HttpResponse
    from rest_framework.views import APIView
    from . import models
    
    
    from rest_framework import serializers
    
    #要先写一个序列化的类
    class RolesSerializer(serializers.Serializer):
        #Role表里面的字段id和title序列化
        id = serializers.IntegerField()
        title = serializers.CharField()
    
    class RolesView(APIView):
        def get(self,request,*args,**kwargs):
            # 方式一:对于[obj,obj,obj]
            # (Queryset)
            roles = models.Role.objects.all()
            # 序列化,两个参数,instance:接受Queryset(或者对象)   mangy=True表示对Queryset进行处理,mant=False表示对对象进行进行处理
            ser = RolesSerializer(instance=roles,many=True)
            # 转成json格式,ensure_ascii=False表示显示中文,默认为True
            ret = json.dumps(ser.data,ensure_ascii=False)
            return HttpResponse(ret)

    (4)浏览器访问:http://127.0.0.1:8000/api/v1/roles/

     可以显示后台返回的json数据

     (5)方式二

    class RolesView(APIView):
        def get(self,request,*args,**kwargs):
            # 方式一:对于[obj,obj,obj]
            # (Queryset)
            # roles = models.Role.objects.all()
            # 序列化,两个参数,instance:Queryset  如果有多个值,就需要加 mangy=True
            # ser = RolesSerializer(instance=roles,many=True)
            # 转成json格式,ensure_ascii=False表示显示中文,默认为True
            # ret = json.dumps(ser.data,ensure_ascii=False)
    
            # 方式二:
            role = models.Role.objects.all().first()
            ser = RolesSerializer(instance=role, many=False)
            ret = json.dumps(ser.data, ensure_ascii=False)
            return HttpResponse(ret)

    只获取一个

    进阶使用

    (1)urls.py

    添加一个info

    urlpatterns = [
        re_path('(?P<version>[v1|v2]+)/roles/', RolesView.as_view()),   #序列化
        re_path('(?P<version>[v1|v2]+)/info/', UserInfoView.as_view()),   #序列化
    ]

    (2)views.py

    class UserInfoSerializer(serializers.Serializer):
        '''序列化用户的信息'''
        #user_type是choices(1,2,3),显示全称的方法用source
        type = serializers.CharField(source="get_user_type_display")
        username = serializers.CharField()
        password = serializers.CharField()
        #group.title:组的名字
        group = serializers.CharField(source="group.title")
        #SerializerMethodField(),表示自定义显示
        #然后写一个自定义的方法
        rls = serializers.SerializerMethodField()
    
        def get_rls(self,row):
            #获取用户所有的角色
            role_obj_list = row.roles.all()
            ret = []
            #获取角色的id和名字
            #以字典的键值对方式显示
            for item in role_obj_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(instance=users,many=True)
            ret = json.dumps(ser.data,ensure_ascii=False)
            return HttpResponse(ret)

    自定义方法

     (3)浏览器访问:http://127.0.0.1:8000/api/v1/info/

    2.继承 ModelSerializer

    把上面的UserInfoSerializer改成继承ModelSerializer的用法

    # class UserInfoSerializer(serializers.Serializer):
    #     '''序列化用户的信息'''
    #     #user_type是choices(1,2,3),显示全称的方法用source
    #     type = serializers.CharField(source="get_user_type_display")
    #     username = serializers.CharField()
    #     password = serializers.CharField()
    #     #group.title:组的名字
    #     group = serializers.CharField(source="group.title")
    #     #SerializerMethodField(),表示自定义显示
    #     #然后写一个自定义的方法
    #     rls = serializers.SerializerMethodField()
    #
    #     def get_rls(self,row):
    #         #获取用户所有的角色
    #         role_obj_list = row.roles.all()
    #         ret = []
    #         #获取角色的id和名字
    #         #以字典的键值对方式显示
    #         for item in role_obj_list:
    #             ret.append({"id":item.id,"title":item.title})
    #         return ret
    
    
    class UserInfoSerializer(serializers.ModelSerializer):
        type = serializers.CharField(source="get_user_type_display")
        group = serializers.CharField(source="group.title")
        rls = serializers.SerializerMethodField()
    
        def get_rls(self, row):
            # 获取用户所有的角色
            role_obj_list = row.roles.all()
            ret = []
            # 获取角色的id和名字
            # 以字典的键值对方式显示
            for item in role_obj_list:
                ret.append({"id": item.id, "title": item.title})
            return ret
    
        class Meta:
            model = models.UserInfo
            fields = ['id','username','password','type','group','rls']
    
    class UserInfoView(APIView):
        '''用户的信息'''
        def get(self,request,*args,**kwargs):
            users = models.UserInfo.objects.all()
            ser = UserInfoSerializer(instance=users,many=True)
            ret = json.dumps(ser.data,ensure_ascii=False)
            return HttpResponse(ret)

    结果一模一样

    3.自动序列化连表(depth)

    继续优化上面的代码,用depth更简单方便

    class UserInfoSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.UserInfo
            #fields = "__all__"
            fields = ['id','username','password','group','roles']
            #表示连表的深度
            depth = 1
    
    
    class UserInfoView(APIView):
        '''用户的信息'''
        def get(self,request,*args,**kwargs):
            users = models.UserInfo.objects.all()
            ser = UserInfoSerializer(instance=users,many=True)
            ret = json.dumps(ser.data,ensure_ascii=False)
            return HttpResponse(ret)

    访问:http://127.0.0.1:8000/api/v1/info/

    4.生成url

    url.py

    urlpatterns = [
        re_path('(?P<version>[v1|v2]+)/group/(?P<pk>d+)/', GroupView.as_view(),name = 'gp')    #序列化生成url
    ]

    views.py

    class UserInfoSerializer(serializers.ModelSerializer):
        group = serializers.HyperlinkedIdentityField(view_name='gp',lookup_field='group_id',lookup_url_kwarg='pk')
        class Meta:
            model = models.UserInfo
            #fields = "__all__"
            fields = ['id','username','password','group','roles']
            #表示连表的深度
            depth = 0
    
    
    class UserInfoView(APIView):
        '''用户的信息'''
        def get(self,request,*args,**kwargs):
            users = models.UserInfo.objects.all()
            #这里必须要传参数context={'request':request}
            ser = UserInfoSerializer(instance=users,many=True,context={'request':request})
            ret = json.dumps(ser.data,ensure_ascii=False)
            return HttpResponse(ret)
    
    
    class GroupSerializer(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 = GroupSerializer(instance=obj,many=False)
            ret = json.dumps(ser.data,ensure_ascii=False)
            return HttpResponse(ret)

    访问:http://127.0.0.1:8000/api/v1/info/

    可以获取到group的url

    5.用户请求数据验证

    基本验证

    (1)url.py

    urlpatterns = [
        re_path('(?P<version>[v1|v2]+)/usergroup/', UserGroupView.as_view(),)    #序列化做验证
    ]

    (2)views.py

    class UserGroupSerializer(serializers.Serializer):
        title = serializers.CharField()
    
    class UserGroupView(APIView):
        def post(self,request,*args, **kwargs):
            ser = UserGroupSerializer(data=request.data)
            if ser.is_valid():
                print(ser.validated_data['title'])
            else:
                print(ser.errors)
    
            return HttpResponse("用户提交数据验证")

    用postman发送正确的数据,后台可以拿到

    发送空数据,会自动验证数据的合法性

     自定义验证规则

     views.py

    添加一个自定义验证

    #自定义验证规则
    class GroupValidation(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)
    
    
    class UserGroupSerializer(serializers.Serializer):
        title = serializers.CharField(validators=[GroupValidation('以我开头'),])    
    
    class UserGroupView(APIView):
        def post(self,request,*args, **kwargs):
            ser = UserGroupSerializer(data=request.data)
            if ser.is_valid():
                print(ser.validated_data['title'])
            else:
                print(ser.errors)
    
            return HttpResponse("用户提交数据验证")

     提交不合法的数据

     后台报错

     提交正确的数据

     
     
     
  • 相关阅读:
    进程对象的属性或方法详解
    进程理论以及开启子进程的两种方式
    计算机发展史(多道技术)
    基于socketserver实现的并发(tcp和udp)
    基于udp协议的套接字及udp协议粘包问题
    模拟ssh的远程网络传输
    周考题目及答案
    c/s架构搭建
    网络编程基础
    10.16模拟赛(湖南集训)
  • 原文地址:https://www.cnblogs.com/gaidy/p/12105638.html
Copyright © 2011-2022 走看看