zoukankan      html  css  js  c++  java
  • 「Django」rest_framework学习系列-序列化

    序列化
    方式一 :在业务类里序列化数据库数据

    class RolesView(APIView):
        def get(self,request,*args,**kwargs):
            roles = models.Role.objects.all().values('id','title')[1:3]
            ret = list(roles)
            r = json.dumps(ret,ensure_ascii=False)
            return HttpResponse(r)
    View Code

    方式二:写个序列化的类,在业务类中引用,序列化类中可以定制字段

    class UserinfoSerializer(serializers.ModelSerializer):
        #字段名与数据库相同则替换,不同则添加
        type = serializers.CharField(source='get_usertype_display')
        gb = serializers.CharField(source='group.title')
        class Meta:
            model = models.UserInfo
            #全部显示
            fields = '__all__'
            #定制显示
            # fields = ['id','username','type','gb']
    定制类
    class UserInfo(models.Model):
        usertype_choices = (
            (1,'普通用户'),
            (2,'VIP用户'),
            (3,'SVIP用户')
        )
        usertype = models.IntegerField(choices=usertype_choices,verbose_name='用户类型')
        username = models.CharField(max_length=32,unique=True,verbose_name='用户名')
        password = models.CharField(max_length=64,verbose_name='密码')
        group = models.ForeignKey('UserGroup',on_delete=models.DO_NOTHING,verbose_name='分组')
        roles = models.ManyToManyField('Role',verbose_name='职业')
        class Meta:
            verbose_name = '用户管理'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.username
    对应数据库结构
    class UserInfoView(APIView):
        authentication_classes = []
        permission_classes = []
        def get(self,request,*args,**kwargs):
            m = models.UserInfo.objects.all()
            ser = UserinfoSerializer(instance=m,many=True)
            #单表的话这里many = false
            return Response(ser.data)    
    业务类

    方式二补充:source不适合many to many,many to many需要自定义显示

    role = serializers.SerializerMethodField() #自定义显示
    def get_role(self,row):
         role_list = row.roles.all()
         ret = []
         for item in role_list:
             ret.append({'id':item.id,'title':item.title})
         return ret
    many to many

    方式三:depth根本连表结构往深层取值

    class UserinfoSerializer(serializers.ModelSerializer):
        usertype = serializers.CharField(source='get_usertype_display')
        class Meta:
            model = models.UserInfo
            #全部显示
            fields = '__all__'
            depth = 1  #0~10之间
            #定制显示
            # fields = ['id','username','type','gb']
    定制类
    [{"id": 1, "usertype": 1, "username": "wrx", "password": "123", "group": {"id": 1, "title": "A组"}, "roles": [{"id": 2, "title": "老师"}, {"id": 3, "title": "医生"}]}, 
    {"id": 2, "usertype": 2, "username": "ylp", "password": "123", "group": {"id": 2, "title": "B组"}, "roles": [{"id": 3, "title": "医生"}]}]
    取值结果

    方式四:生成链接,即把上述类的group生成链接

    class UserinfoSerializer(serializers.ModelSerializer):
        usertype = serializers.CharField(source='get_usertype_display')
        group = serializers.HyperlinkedIdentityField(view_name='grp',lookup_field='group_id',lookup_url_kwarg='pk')
        #name,pk值对应urls中的re-path
        class Meta:
            model = models.UserInfo
            #全部显示
            fields = '__all__'
            depth = 1  #0~10之间
            #定制显示
            # fields = ['id','username','type','gb']
    定制类
    re_path(r'^(?P<version>[v1|v2]+)/group/(?P<pk>d+)$',GroupView.as_view(),name='grp')
    PS:这里经历了一个错误,如果配置了全局的版本控制(详见版本控制配置),这里要也要配置,否则会一直报错
    django.core.exceptions.ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "grp". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.
    class UserInfoView(APIView):
        def get(self,request,*args,**kwargs):
            m = models.UserInfo.objects.all()
            ser = UserinfoSerializer(instance=m,many=True,context={'request':request})
            return Response(ser.data)
    Views业务类

    PS:实例这个定制类的时候要加要加context={'request':request}

    实际调用的是另一个views类的url

    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)
            t = json.dumps(ser.data, ensure_ascii=False)
            return HttpResponse(t)
    上面re_path对应的定制类和业务类

    方式五:三张表互相关联的反向查找

    class Course(models.Model):
        title = models.CharField(max_length=32,verbose_name='课程名称')
        course_img = models.ImageField(verbose_name='课程图片',upload_to = "static/img/")
        course_choice = (
            (0, '入门级'),
            (1, '普通难度'),
            (2, '中等难度'),
            (3, '高级难度'),
        )
        level = models.IntegerField(verbose_name='课程难度',choices=course_choice,default=0)
    
        class Meta:
            verbose_name = '课程管理'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return self.title
    
    class CourseInfo(models.Model):
        why = models.CharField(verbose_name='课程描述',max_length=255)
        course = models.OneToOneField(to='Course',on_delete=models.DO_NOTHING,verbose_name='关联课程')
        recommend_course = models.ManyToManyField(to='Course',verbose_name='推荐课程',related_name='rc')
    
        class Meta:
            verbose_name = '课程详细'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return '课程详细:'+self.course.title
    
    class Section(models.Model):
        num = models.IntegerField(verbose_name='章节')
        name = models.CharField(max_length=64,verbose_name='课程章节')
        course = models.ForeignKey(to='Course', on_delete=models.DO_NOTHING, verbose_name='关联课程')
    
        class Meta:
            verbose_name = '课程章节'
            verbose_name_plural = verbose_name
    
        def __str__(self):
            return '课程章节'+self.course.title
    表结构

    PS:第二张表与第一张表多对多并且单对单(这里有个小知识点,同时多对多和单对单的时候有一张表要加related_name='rc'),第三张表与第一张表一对多,需求:通过序列化第二张表得到第一张表和第三张表的相关内容

    class CourseinfoSerializer(serializers.ModelSerializer):
        #单对单,单对多,choice可以用这种方式,多对多不能使用
        title = serializers.CharField(source='course.title')
        level = serializers.CharField(source='course.get_level_display')
        #多对多需要自定义
        recommends = serializers.SerializerMethodField()
        def get_recommends(self, row):
            role_list = row.recommend_course.all()
            ret = []
            for item in role_list:
                ret.append({'id': item.id, 'title': item.title})
            return ret
        #3张表互相关联的反向查找
        sections = serializers.SerializerMethodField()
        def get_sections(self, row):
            role_list = row.course.section_set.all()
            ret = []
            for item in role_list:
                ret.append({'num': item.num, 'name': item.name})
            return ret
        class Meta:
            model = models.CourseInfo
            # fields = '__all__'
            fields = ['id','title','level','why','recommends','sections']
            # depth = 2
    定制类
        def retrieve(self,request, *args, **kwargs):
            ret = {'code': 1000, 'data': None}
            pk = kwargs.get('pk')
            try:
                obj = models.CourseInfo.objects.filter(course_id=pk)
                ser = sl.CourseinfoSerializer(instance=obj, many=True)
                ret['data'] = ser.data
            except Exception as e:
                ret['code'] = 1001
                ret['error'] = '获取课程失败'
            return Response(ret)
    业务类

    PS:这实际是个类的get请求,re_path(r'^course/(?P<pk>d+)$',views.CourseView.as_view({'get':'retrieve'})),

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    序列化-数据验证,验证title数据不能为空且必须以wrx开头

    class UserGroupSerializer(serializers.Serializer):
        title = serializers.CharField(error_messages={'required':'标题不能为空'},)
        def validate_title(self,value):
            if not value.startswith('wrx'):
                message = '标题必须以%s开头'%'wrx'
                raise exceptions.ValidationError(message)
            else:
                return value
    定制类
    class UserGroupView(APIView):
        def post(self,request,*args,**kwargs):
            src = ''
            res = UserGroupSerializer(data=request.data)
            if res.is_valid():
                print(res.validated_data)
                src = str(res.validated_data['title'])
            else:
                print(res.errors)
                src = str(res.errors)
            return HttpResponse(src)
    业务类
  • 相关阅读:
    UML简单熟悉
    Java设计模式--单例模式
    MyEclipse2014安装图解
    让Win10显示系统中隐藏的文件夹
    Ping命令
    C语言学习
    技术学习论坛地址收集
    聊聊JVM的年轻代(转)
    深入理解JVM--JVM垃圾回收机制(转)
    JVM调优浅谈(转)
  • 原文地址:https://www.cnblogs.com/wrxblog/p/10402580.html
Copyright © 2011-2022 走看看